Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kivy - Limit Values on InputText

I'm trying to make an input text that only accept float values. In addition, the value entered must be between two values.

I created a class that contain a 'validate' method. If the value is not between two values, a Popup is showed.

But I have a problem. The method is only called when the user hit 'Enter'. I tried call the method when the text is changed, but it is annoying for the user, because the Popup appears all the time while the user is entering the data.

There is another approach to do something like this?

Python file:

class BoundedInput(BoxLayout):
    value = NumericProperty()

    def validate(self, min_value, max_value):
        status = min_value <= self.value <= max_value
        if not status:
            message = f'Value must be between {min_value} and {max_value}'
            popup = Popup(title='Warning', content=Label(text=message),
                            size_hint=(None, None), size=(300, 200))
            popup.open()

Kv file:

<NumericInput@TextInput>:
    input_filter: 'float'
    multiline: False

<BoundedInput>:
    orientation: 'horizontal'
    Label:
        text: 'Value'
    NumericInput:
        text: str(root.value)
        on_text_validate:
            root.value = float(self.text)
            root.validate(5, 100)
like image 903
Eduardo Avatar asked Mar 08 '23 02:03

Eduardo


1 Answers

A suitable approach could be filtering in addition to floating this also within the range for it we create a class that inherits TextInput and overwrite the insert_text method:

from kivy.app import App
from kivy.base import Builder
from kivy.properties import NumericProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput


Builder.load_string("""
<BoundedLayout>:
    orientation: 'horizontal'
    Label:
        text: 'Value'
    NumericInput:
        min_value : 5
        max_value : 100
        hint_text : 'Enter values between {} and {}'.format(self.min_value, self.max_value)
""")

class NumericInput(TextInput):
    min_value = NumericProperty()
    max_value = NumericProperty()
    def __init__(self, *args, **kwargs):
        TextInput.__init__(self, *args, **kwargs)
        self.input_filter = 'float'
        self.multiline = False

    def insert_text(self, string, from_undo=False):
        new_text = self.text + string
        if new_text != "":
            if self.min_value <= float(new_text) <= self.max_value:
                TextInput.insert_text(self, string, from_undo=from_undo)

class BoundedLayout(BoxLayout):
    pass

class MyApp(App):
    def build(self):
        return BoundedLayout()

if __name__ == '__main__':
    MyApp().run()
like image 128
eyllanesc Avatar answered Mar 31 '23 10:03

eyllanesc