Reputation: 4749
Is there a way for TextInput
s to receive a bounded string value (i.e., string of maximum length, x)? I tried investigating how to mixin AliasProperty
in order to mimic BoundedNumericProperty
, but can't find any Property class methods.
Upvotes: 3
Views: 1219
Reputation: 189
There is simple problem with the code given above. you have to use NumericProperty.defaultvalue in order to use the code ( in the length comparison). Below is simple child class that can be used to create the classes for any size you deem fit.
class CustomInput(TextInput):
def __init__(self , **kwargs):
if "max_chars" in kwargs:
self.max_chars = NumericProperty(int(kwargs["max_chars"]))
super(CustomInput , self ).__init__(**kwargs)
def insert_text( self , substring , from_undo = False ):
if not from_undo and ( len( self.text ) + len( substring ) > self.max_chars.defaultvalue ):
return
super( CustomInput , self).insert_text( substring , from_undo)
i pass max_chars as a keyword argument to the init. this works if i use just int for max_chars instead of NumericProperty
Upvotes: 1
Reputation: 4162
By the time on_text
is called text is already changed in the textinput. You want to override insert_text to catch the text before it is inserted into the TextInput and thus before the text property is updated so as to restrict the entry to the TextInput.
Please don't bind/request the keyboard as the textinput does that for you and your handler will stop working after the Textinput is focused (TextInput would request the keyboard and in a single keyboard environment your handler will stop working).
Here is a sample code overriding insert_text to restrict text text entry to only numeric input.
class NumericInput(TextInput):
def insert_text(self, substring, from_undo=False):
if not from_undo:
try:
int(substring)
except ValueError:
return
super(NumericInput, self).insert_text(substring, from_undo)
So For restricting the text to a certain length you could do the following::
class CustomInput(TextInput):
max_chars = NumericProperty(10)
def insert_text(self, substring, from_undo=False):
if not from_undo and (len(self.text)+len(substring) > self.max_chars):
return
super(CustomInput, self).insert_text(substring, from_undo)
Upvotes: 7
Reputation: 19027
I think that the event on_text
is triggered each time you modify the text. So you can override the method:
def on_text(self, instance, value):
print('The widget', instance, 'have:', value)
# validate here!!!
# you might also want to call the parent.
#super(ClassName, self).on_text(instance, value)
Or bind it:
def my_callback(instance, value):
print('The widget', instance, 'have:', value)
#validate here
textinput = TextInput()
textinput.bind(text=my_callback)
Be careful with the infinitive recursion. If you modify the text variable inside on_text
or my_callback
you might be triggering the event ago. I honestly don't remember but I think it does, so you need a flag such as validating before modifying the variable
You can also use still use on_focus
so you check when the TextInput
lost focus:
def on_focus(instance, value):
if value:
print('User focused', instance)
else:
print('User defocused', instance)
textinput = TextInput()
textinput.bind(focus=on_focus)
Finally, you can also bind the keyboard so you will guarantee access before the TextInput
. I honestly don't know the order of execution but if you use on_text
you might be deleting after the letter appearing on the screen which might be undesirable.
I think implementing your own BoundedStringProperty
would be quite a work to achieve what you want. Here is the code of BoundedNumericProperty
Also, you shouldn't be trying to use an AliasProperty
since you already got StringProperty
that triggers the on_text
event mentioned before.
Upvotes: 3