Search code examples
pythonkivy

Kivy: Clearing Text Input with 'on focus' or 'on_touch_down'


I want to clear a TextInput's text: when I click on it. Sample Code:

from kivy.app import App
from kivy.lang import Builder

kv_string = """
ScreenManager:
    id: manager
    Screen:
        BoxLayout:
            orientation: 'vertical'
            Button:
                text: 'Why does it clear multiple inputs? And why do they get cleared after touch_up?'
            TextInput:
                text: 'Write Your Name'
                on_touch_down:
                    self.text = ''

            TextInput:
                text: 'Write Your Last Name'
                on_focus:
                    self.text = ''

            TextInput:
                text: 'Write Your Phone Number'
                on_touch_down:
                    self.text = ''
"""

class MyApp(App):

    def build(self):
        root_widget = Builder.load_string(kv_string)
        return root_widget

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

Neither on_touch_down: or on_focus erases JUST the text input that is currently focused. Instead, both get cleared when I touch anywhere on the screen. I would want them cleared individually once the cursor is on a text input. I also tried on_cursor but that didn't work either. What am I missing? Thank you in advance!


Solution

  • The on_touch_down event is received by all the widgets until one returns True telling the event-loop that it is using it and thus not send it to other widgets as indicated by the docs:

    on_touch_down(touch) Added in 1.0.0

    Receive a touch down event.

    Parameters:

    touch: MotionEvent class Touch received.

    The touch is in parent coordinates. See relativelayout for a discussion on coordinate systems.

    Returns:

    bool If True, the dispatching of the touch event will stop. If False, the event will continue to be dispatched to the rest of the widget tree.

    The classic use of on_touch_down is in python since kv language is limited in the overwriting of methods:

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.textinput import TextInput
    
    class MyTextInput(TextInput):
        def on_touch_down(self, touch):
            if self.collide_point(*touch.pos):
                self.text = ""
                return True
            return super(MyTextInput, self).on_touch_down(touch)
    
    kv_string = """
    ScreenManager:
        id: manager
        Screen:
            BoxLayout:
                orientation: 'vertical'
                Button:
                    text: 'Why does it clear multiple inputs? And why do they get cleared after touch_up?'
                MyTextInput:
                    text: 'Write Your Name'
                MyTextInput:
                    text: 'Write Your Last Name'  
                MyTextInput:
                    text: 'Write Your Phone Number'
    """
    
    class MyApp(App):
        def build(self):
            root_widget = Builder.load_string(kv_string)
            return root_widget
    
    if __name__ == "__main__":
        MyApp().run()
    

    Or something equivalent in .kv but the devestaja is that you can not return True.

    kv_string = """
    ScreenManager:
        id: manager
        Screen:
            BoxLayout:
                orientation: 'vertical'
                Button:
                    text: 'Why does it clear multiple inputs? And why do they get cleared after touch_up?'
                TextInput:
                    text: 'Write Your Name'
                    on_touch_down: if self.collide_point(*args[1].pos): self.text = ""
                TextInput:
                    text: 'Write Your Last Name'
                    on_touch_down: if self.collide_point(*args[1].pos): self.text = ""
                TextInput:
                    text: 'Write Your Phone Number'
                    on_touch_down: if self.collide_point(*args[1].pos): self.text = ""
    """
    

    So you should use on_focus which is an event associated to FocusBehavior that overwrites on_touch_down verifying using self.collide_point(*touch.pos).

    from kivy.app import App
    from kivy.lang import Builder
    
    kv_string = """
    ScreenManager:
        id: manager
        Screen:
            BoxLayout:
                orientation: 'vertical'
                Button:
                    text: 'Why does it clear multiple inputs? And why do they get cleared after touch_up?'
                TextInput:
                    text: 'Write Your Name'
                    on_focus: self.text = ""
                TextInput:
                    text: 'Write Your Last Name'
                    on_focus: self.text = ""
                TextInput:
                    text: 'Write Your Phone Number'
                    on_focus: self.text = ""
    """
    
    class MyApp(App):
        def build(self):
            root_widget = Builder.load_string(kv_string)
            return root_widget
    
    if __name__ == "__main__":
        MyApp().run()