Kv LanguageをPython側でどう処理されてるか見るためにPythonのみで色々実装しようとしたら失敗続きで2日程悩んだので自戒をこめて書いとく。
Button実装
main.py:
from kivy.app import App from kivy.uix.button import Button class MainApp(App) def build(self): pass
main.kv:
Button: text: "hoge"
は
from kivy.app import App class MainApp(App): def build(self): return Button(text="hoge")
と書き換えられる。
Labelも同じ感じなので割愛
Buttonを押したときのEvent処理
Python Kivyの使い方① ~Kv Languageの基本~の10項を例にする。
今回はクラスを新たに作らず全てMainAppクラス内で済ませるようにした。(正直、新しくクラス作ったほうが可読性は上がる)
main.py:
from kivy.app import App from kivy.properties import StringProperty class MainApp(App): text = StringProperty() btn_text = StringProperty() def __init__(self, **kwargs): super().__init__(**kwargs) self.text = "" self.btn_text = "Button" def build(self): pass def pressed(self): if self.text != "": self.text = "" self.btn_text = "Blank" else: self.text = "Hello World" self.btn_text = "Changed"
main.kv:
BoxLayout: orientation: 'vertical' size: root.size Label: id: label1 font_size: 68 text: app.text Button: id: button1 text: app.btn_text font_size: 68 on_press: app.pressed()
は
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.uix.button import Button class MainApp(App): def __init__(self, **kwargs): super().__init__(**kwargs) self.label = Label(text="", font_size=48) self.button = Button(text="Button", font_size=48, on_press=self.pressed) def pressed(self, *args): if self.label.text != "": self.label.text = "" self.button.text = "Blank" else: self.label.text = "Hello World" self.button.text = "Changed" def build(self): boxlay = BoxLayout(orientation="vertical") boxlay.add_widget(self.label) boxlay.add_widget(self.button) return boxlay
と書き換えられる。
ここで注意が2つある。
一つは
self.button = Button(text="Button", font_size=48, on_press=self.pressed)
でon_press=self.pressed()
とはしないこと。
この場合、Event: on_pressの値をcallback関数に指定する必要があり、self.pressed()
だと返された(returnで返ってきた)値を代入してしまうこととなる。
もう一つは
def pressed(self, *args):
で必ず引数を(使わずとも)追加する必要がある。理由としては、pressed
関数はcallback関数なので引数に自身のインスタンス(self)ともう一つ、呼んだ関数のインスタンス(この場合MainApp())を必要とする。そのため、pressed
関数を利用するためにはこの場合2つの引数が必要となる。
呼んだ関数のインスタンスを利用したい場合は*args
をinstance
とかに変えれば良い。使わないなら基本的に引数は*args
で十分。
参考:
公式リファレンス - Button (英語)
また、pressed関数に他の引数を追加したい場合はfunctools
モジュールからpartial
をimportして
self.button = Button(text="Button", font_size=48, on_press=partial(self.pressed, <arg1>, <arg2>...)
とする。(self.pressed(<arg1>, <arg2>...)
は先述したとおりreturnされた値を代入してしまう。)
そしてpressed
関数を
def pressed(self, instance, <arg1>, <arg2>, ...):
とする。
LabelまたはButtonのtextを変えたい場合は
self.label = Label(text="", font_size=48) self.button = Button(text="Button", font_size=48, on_press=self.pressed)
のように変数を作り、
self.label.text = "" self.button.text = "Blank"
のようにクラス変数の値を変えれば良い。
今回示した例とけっこう違う方法で実装することも可能なので、随時更新していきたい。