user3060854
user3060854

Reputation: 933

kivy, how to trigger event by text change

Several GUI toolboxes include events such as on_change which are triggered every time the text in a textbox changes.

According to this: https://kivy.org/docs/api-kivy.uix.textinput.html the on_text event should be equal. So, I created a single TextInput box expecting everytime a change a single letter, the content of the box to be displayed in the terminal. This is the code:

from kivy.app import App
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout

class LoginScreen(BoxLayout):

    def __init__(self, **kwargs):
        super(LoginScreen, self).__init__(**kwargs)
        self.orientation = 'horizontal'
        self.mytext = TextInput(text='500', multiline = False)
        self.add_widget(self.mytext)

        self.mytext.bind(on_text = self.calc)
        #self.mytext.bind(on_text_validate = self.calc)

    def calc(self, mytext):
        print mytext.text

class MyApp(App):

    def build(self):
        return LoginScreen()

if __name__ == '__main__':
    MyApp().run()

Yet, nothing happens, which obviously means that the calc function is not triggered at all. Mind that the on_text_validate event works fine, because the contents of the box are printed in the terminal when I press Enter.

So, did I misunderstand the on_text event, and if so, how can I accomplish my goal?

Upvotes: 5

Views: 9305

Answers (1)

FJSevilla
FJSevilla

Reputation: 4533

on_text is not a TextInput event. To run a callback when the text changes, you can bind text property (where textinput’s text is stored):

from kivy.app import App
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout

class LoginScreen(BoxLayout):

    def __init__(self, **kwargs):
        super(LoginScreen, self).__init__(**kwargs)
        self.orientation = 'horizontal'
        self.mytext = TextInput(text='500', multiline = False)
        self.add_widget(self.mytext)
        self.mytext.bind(text = self.calc)
        
    def calc(self, instance, text):
        print(text)

class MyApp(App):

    def build(self):
        return LoginScreen()

if __name__ == '__main__':
    MyApp().run()

You can create callback that automatic is called when a property change using on_<property_name> sintax:

  • Kivy Languaje:

      from kivy.app import App
      from kivy.uix.boxlayout import BoxLayout
      from kivy.lang import Builder
    
      Builder.load_string('''\
      <LoginScreen>:
          orientation: "horizontal"
          TextInput:
              text: "500"
              on_text: root.calc(self.text)
      ''')
    
      class LoginScreen(BoxLayout):
          def __init__(self, **kwargs):
              super(LoginScreen, self).__init__(**kwargs)
    
          def calc(self, text):
              print(text)
    
      class MyApp(App):
    
          def build(self):
              return LoginScreen()
    
      if __name__ == '__main__':
          MyApp().run()
    
  • Extending widget class:

      from kivy.app import App
      from kivy.uix.textinput import TextInput
      from kivy.uix.boxlayout import BoxLayout
    
      class My_TextInput(TextInput):
          def __init__(self, **kwargs):
              super(My_TextInput, self).__init__(**kwargs)
    
          def on_text(self, instance, text):
              print(text)
    
      class LoginScreen(BoxLayout):
          def __init__(self, **kwargs):
              super(LoginScreen, self).__init__(**kwargs)
              self.mytext = My_TextInput(text='500', multiline = False)
              self.add_widget(self.mytext)
    
    
      class MyApp(App):
    
          def build(self):
              return LoginScreen()
    
      if __name__ == '__main__':
          MyApp().run()
    

Upvotes: 13

Related Questions