Kivyで任意のwidgetをクリックしたらそのままテキストボックスに入力ができるようにするの巻
はじめに
Kivyでテキストボックスを作ったときに、任意のwidgetをクリック(タップ)したら、紐づけたテキストボックスがアクティブになってそのままテキスト入力ができるようにしたいぞ、と
こんな感じに。
Labelをダブルタップするとtextinput1がアクティブになって入力ができるようになる。
Buttonをクリックするとtextinput2がアクティブになって入力ができるようになる。
と、いうことをやる方法の備忘録です。
やり方
以下の2つを組み込めば良かったのでした。
- Labelをダブルタップしたら(Buttonをクリックしたら)対応するテキストボックスのfocusをTrueにする
- Clockを使って、1.を少し遅れて実行することで、タップ(クリック)イベントが完了してからTextInputにfocusが行くようにする
コード
冒頭の動画のやつのコードです。
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.clock import Clock
Builder.load_string('''
<Otameshi>
orientation: 'vertical'
BoxLayout:
TextInput:
id: textinput1desu
hint_text: 'textinput1 for Label'
TextInput:
id: textinput2desu
hint_text: 'textinput2 for Button'
Label:
id: labeldesu
text: 'Label dayo'
font_size: 80
#args[1]; mouse pos correspond to args 'touch' for on_touch_down
on_touch_down: root.focus_from_label(args[1])
Button:
id: buttondesu
text: 'Button dayo'
font_size: 80
on_press: root.focus_from_button()
<TextInput>
padding: 30,150
font_size: 80
''')
#give class the name of Otameshi
class Otameshi(BoxLayout):
#for label
def focus_from_label(self, touch):
#execute if touch is double tap on the widget(Label)
if self.ids.labeldesu.collide_point(*touch.pos) and touch.is_double_tap:
#assign textinput object to a variable
target_textinput = self.ids.textinput1desu
#wait for 0.5 sec to execute function to keep focus maintained
Clock.schedule_once(lambda dt: self.focus_callback(target_textinput, dt=dt), 0.5)
#for button
def focus_from_button(self):
#assign textinput object to a variable
target_textinput = self.ids.textinput2desu
#wait for 0.5 sec to execute function to keep focus maintained
Clock.schedule_once(lambda dt: self.focus_callback(target_textinput, dt=dt), 0.5)
#for Clock function above
def focus_callback(self, target_textinput, dt, *kwargs):
#turn focus to True
target_textinput.focus=True
#give class the name of App
class TextInputtestApp(App):
def __init__(self, **kwargs):
super(TextInputtestApp, self).__init__(**kwargs)
def build(self):
return Otameshi()
if __name__ == '__main__':
TextInputtestApp().run()
コードの説明をざっくり
・Labelをダブルタップしたとき(on_touch_down)の関数; focus_from_label を定義。タップしたときのargs[1]をtouchとして入力に持ってくる。
def focus_from_label(self, touch):
・Labelウィジェット(id: labeldesu)のところでon_touch_downイベントが起こっていて、かつそれがダブルタップだった時に処理を実行する
if self.ids.labeldesu.collide_point(*touch.pos) and touch.is_double_tap:
・変数target_textinputに左側のTextInputオブジェクト(id: textinput1desu)を入れておく
target_textinput = self.ids.textinput2desu
・Clock.schedule_onceにより、Labelをダブルタップしたときの関数(focus_callback)の実行を少し遅らせて(今回0.5秒)、タップイベントが終わった後にfocusがTextInputに行くようにしておく (0.5秒より短くしてもいいかも)
Clock.schedule_once(lambda dt: self.focus_callback(target_textinput, dt=dt), 0.5)
・Buttonのときの関数設定部分はLabelのときの関数の流用なので割愛
・Clockのところのfocus_callback関数の定義。target_textinputのfocusをTrueにする
def focus_callback(self, target_textinput, dt, *kwargs): target_textinput.focus=True
で、OKと。これで冒頭の動画のような挙動にできるはず。
めでたしめでたし。
実施環境
Python 3.9.4
Kivy 2.0.0
macOS Catalina ver.10.15.7
参考にしたページ
・Stack Overflow
Python KIVY: how to select a TextInput without mouse click?
・Clockの説明 Kivy Official
https://pyky.github.io/kivy-doc-ja/api-kivy.clock.html
・on_touch_downの引数について
https://start-python.hateblo.jp/entry/2020/01/12/090000
https://business.xserver.ne.jp/
https://www.xdomain.ne.jp/
★LOLIPOP★
.tokyo
MuuMuu Domain!