Basically I've been working on a Kivy application with multiple screens, and I'm trying to make it so that it will take you back to the main screen if the escape button is pressed. Things have been going well, as I followed this question's answer, except the fact that when I focus on a TextInput widget and unfocus, the escape key shortcut, or more specifically the on_key_down
event isn't called anymore.
Anyone knows what's wrong? Any helps would be appreciated!
Edit: Here's my code, shortened and simplified:
test.py
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.config import Config
Config.set('kivy', 'exit_on_escape', 0)
class MainScreen(Screen):
def __init__(self, **kwargs):
super(Screen, self).__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(keycode[1])
if keycode[1] == 'escape':
if App.get_running_app().root.current == 'Main':
App.get_running_app().stop()
Window.close()
else:
App.get_running_app().root.current = 'Main'
class UhIDontHaveIdeaForANameBecauseItsAnExampleScreen(Screen):
pass
class Test(App):
pass
Test().run()
test.kv
ScreenManager:
MainScreen:
id: Main
UhIDontHaveIdeaForANameBecauseItsAnExampleScreen:
id: Settings
<MainScreen>:
name: 'Main'
BoxLayout:
orientation: 'vertical'
Label:
text: 'idk just press it bruh'
Button:
id: butt
text: 'no clue'
on_release: app.root.current = 'NoClue'
<UhIDontHaveIdeaForANameBecauseItsAnExampleScreen>:
name: 'NoClue'
TextInput:
size_hint: 0.4, 0.1
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
You bind the main screen to listening to the keyboard when you create it but when you focus the Textinput kivy automatically bind the keyboard to the textinput
so the _on_keyboard_down
method in the MainScreen
there are many solution to do this but we need to bind the main screen to the keyboard again so the _on_keyboard_down
start to listening to the keyboard again and we can do this inside the textField
with _on_textinput_focused
method like bellow
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.config import Config
from kivy.uix.textinput import TextInput
Config.set('kivy', 'exit_on_escape', 0)
class MainScreen(Screen):
def __init__(self, **kwargs):
super(Screen, self).__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(keycode[1])
if keycode[1] == 'escape':
if App.get_running_app().root.current == 'Main':
App.get_running_app().stop()
Window.close()
else:
App.get_running_app().root.current = 'Main'
class UhIDontHaveIdeaForANameBecauseItsAnExampleScreen(Screen):
pass
class TextField(TextInput):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def _on_textinput_focused(self, instance, value, *largs):
print(instance.focus)
# test if the text input is focused
if not instance.focus:
app=App.get_running_app()
app.root.ids.Main._keyboard = Window.request_keyboard(app.root.ids.Main._keyboard_closed, self)
app.root.ids.Main._keyboard.bind(on_key_down=app.root.ids.Main._on_keyboard_down)
class Test(App):
pass
Test().run()
and use the TextField
in the kv file
like this
ScreenManager:
MainScreen:
id: Main
UhIDontHaveIdeaForANameBecauseItsAnExampleScreen:
id: Settings
<MainScreen>:
name: 'Main'
BoxLayout:
orientation: 'vertical'
Label:
text: 'idk just press it bruh'
Button:
id: butt
text: 'no clue'
on_release: app.root.current = 'NoClue'
<UhIDontHaveIdeaForANameBecauseItsAnExampleScreen>:
name: 'NoClue'
TextField:
size_hint: 0.4, 0.1
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
<TextField>: