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"
のようにクラス変数の値を変えれば良い。
今回示した例とけっこう違う方法で実装することも可能なので、随時更新していきたい。