Po pierwsze, żeby zamiast korzystać z prawdziwej klawiatury przed biurkiem i klikać na przyciski jak na mobilkach, ustawiamy konfigurację
# to musi być u samej góry przed innymi importami
from kivy.config import Config
Config.set('kivy', 'keyboard_mode', 'dock')
Po drugie, żeby samemu decydować kiedy te klawiatury wirtualne mają się pojawiać i znikać faktycznie modyfikujemy property keyboard_mode
Text Inputów na manage
. Jako że nie chcemy, żeby klawiatura wirtualna nam znikała, ustawiamy jako manage
na wszystkich polach tekstowych, od teraz można je otwierać metodą show_keyboard()
i zamykać metodą hide_keyboard()
:
layout = BoxLayout(orientation='vertical')
text_input_1 = TextInput(keyboard_mode='managed')
text_input_2 = TextInput(keyboard_mode='managed')
empty_space = Widget()
button_1 = Button(text="Button 1")
button_2 = Button(text="Button 2")
layout.add_widget(text_input_1)
layout.add_widget(text_input_2)
layout.add_widget(empty_space)
layout.add_widget(button_1)
layout.add_widget(button_2)
Teraz trzeba ogarnąć jak te klawiatury pokazać tak, by nie znikały przy naciskaniu na przyciski inne widgety. Do kontroli klikania używany jest callback dla zdarzenia on_touch_down
. Wewnątrz możemy sprawdzić, czy kliknęliśmy faktycznie w widget, czy poza nim sprawdzając self.collide_point(*touch.pos)
. A zatem:
def on_touch_down_callback(instance, touch):
if not instance.collide_point(*touch.pos):
# kliknieto poza - nic nie rób
return
# zwolnij poprzednie klawiatury
text_input_1.hide_keyboard()
text_input_2.hide_keyboard()
# natychmiast wyświetl nową dla wybranego pola tekstowego
instance.show_keyboard()
text_input_1.bind(on_touch_down=on_touch_down_callback)
text_input_2.bind(on_touch_down=on_touch_down_callback)
Jeżeli kliknęliśmy poza polem tekstowym, nic nie robimy. W przeciwnym razie zwalniamy poprzednie klawiatury (inaczej klikanie w klawisze będzie nam wpisywało tekst do wszystkich pól tekstowych w jakie kliknęliśmy), po czym pokazujemy nową klawiaturę.
Jeszcze dla zabawy zamontujmy aby drugi przycisk (ale nie pierwszy) nam te klawiatury gasił:
def release_all_keyboards_callback(*args):
text_input_1.hide_keyboard()
text_input_2.hide_keyboard()
button_2.bind(on_press=release_all_keyboards_callback)
Trochę to takie na kolanie pisane, że z palca wypisuje wszystkie widgety zamiast jak człowiek jakoś poiterować po potomkach layoutu, sprawdzając, który z nich to TextInput
i ma akurat wyświetloną klawiaturę, ale niech tam będzie.
Razem do kupy:
from kivy.config import Config
Config.set('kivy', 'keyboard_mode', 'dock')
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivy.clock import Clock
from kivy.base import runTouchApp
layout = BoxLayout(orientation='vertical')
text_input_1 = TextInput(keyboard_mode='managed')
text_input_2 = TextInput(keyboard_mode='managed')
empty_space = Widget()
button_1 = Button(text="Button 1")
button_2 = Button(text="Button 2")
layout.add_widget(text_input_1)
layout.add_widget(text_input_2)
layout.add_widget(empty_space)
layout.add_widget(button_1)
layout.add_widget(button_2)
def on_touch_down_callback(instance, touch):
if not instance.collide_point(*touch.pos):
# clicked outside - do not close anything
return
# zwolnij poprzednie klawiatury
text_input_1.hide_keyboard()
text_input_2.hide_keyboard()
# natychmiast wyświetl nową dla wybranego pola tekstowego
instance.show_keyboard()
text_input_1.bind(on_touch_down=on_touch_down_callback)
text_input_2.bind(on_touch_down=on_touch_down_callback)
def release_all_keyboards_callback(*args):
text_input_1.hide_keyboard()
text_input_2.hide_keyboard()
button_2.bind(on_press=release_all_keyboards_callback)
runTouchApp(layout)
Jakbyśmy chcieli, abyśmy klawiatura była otwarta od początku to można by to np. zrobić w Clock.schedule_once(set_keyboard_for_text_input_1, 0)
.