2
votes

The following code creates a Kivy app with a single screen, MainScreen, displaying a Label and TextInput object.

If you give some keyboard input when the app first loads, it prints in the console with information about which key was pressed. However, if you then click in the TextInput object the keyboard refocuses so you can type in the TextInput object. However, once you click back out of the TextInput object, e.g. on the label or background, and press more keys, the same console printing operation doesn't execute; it seems that the keyboard doesn't 'defocus' from the TextInput object.

How do I recapture keyboard focus after clicking out of a TextInput object?

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.textinput import TextInput

kv = '''ScreenManagement:
    MainScreen:

<MainScreen>:
    name: "main"
    BoxLayout:
        Label:
            text: "Label"
            font_size: 20
            size_hint: 0.2,0.1
        TextInput
            input_filter: 'float'
            font_size: 20
            hint_text: "Input Text"
            size_hint: 0.2,0.1'''

class MainScreen(Screen):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        print('INFO: The key', keycode, 'has been pressed')

        return True # return True to accept the key. Otherwise, it will be used by the system.

class ScreenManagement(ScreenManager):
    pass

class MainApp(App):
    def build(self):
        return Builder.load_string(kv)

if __name__ == "__main__":
    MainApp().run()
1
A user on the Kivy IRC also provided this answer: pastebin.com/nYs4fHvT, which creates a button to re-focus the keyboard.Tom

1 Answers

1
votes

One possible solution is to use the on_touch_down event and reconfigure the keyboard if you press a section that does not contain a TextInput:

class MainScreen(Screen):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.config_keyboard()

    def on_touch_down(self, touch):
        self.isTextInput = False

        def filter(widget):
            for child in widget.children:
                filter(child)
            if isinstance(widget, TextInput) and widget.collide_point(*touch.pos):
                self.isTextInput = True
                widget.on_touch_down(touch)

        filter(self)

        if not self.isTextInput and self._keyboard is None:
            self.config_keyboard()

    def config_keyboard(self):
        self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_closed(self):
        self._keyboard.unbind(on_key_down=self._on_keyboard_down)
        self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        print('INFO: The key', keycode, 'has been pressed')

        return True # return True to accept the key. Otherwise, it will be used by the system.