Python3 マスターへの道:その7
今回は、前回名前を出していた kv 言語についてです。プログラムを作る前に、理解しないといけないことが多そうですね。ですが、kv 言語を理解できれば、また一歩 Kivy で様々プログラムを作ることができるようになれますね。
という事で、いくら書けても、ロードの仕方がわからなければ本末転倒。まずは、kv 言語のロードの方法から。
kv 言語をロードする
ロードの仕方は3つあります。
1:クラス名とファイル名を揃える方法
まず、その1つ目は、実は、前回、お話ししました。それが、App クラスのサブクラスの名前をファイル名に合わせることでした。つまり、kv 言語で書いた Test.kv をロードする場合には、TestApp というApp のサブクラスを作成して、実行しました。
この方法の場合は、ただ名前を揃えて、同じディレクトリに入れただけで、build メソッドのオーバーライドを pass と表記して、ロードできました。
1 class TestApp(App): 2 3 def build(self): 4 pass
2:Builder.load_file を使う方法
この方法では、まず Builder というクラスをインポートします。そして、その load_file メソッドを使って、kv ファイルをロードします。例えば、インポートする kv ファイルで build メソッドをオーバーライドしたい場合には、return の値に、2 行目を組み込むことで、表示する事で、同じ出力が期待できます。
1 class TestApp(App): 2 3 def build(self): 4 return Builder.load_file('path/file.kv')
3:Builder.load_string を使う方法
最後の方法なのですが、この方法でも Builder というクラスをインポートする必要があります。基本的に、load_string メソッドでは、''' で囲まれている中に、kv 言語で表記する事でロードできます。方法は、以下です。
1 class TestApp(App): 2 3 def build(self): 4 return Builder.load_string(''' 5 STRING: 6 ''')
一見、kv 言語の位置に違和感はありますが、試してみたら、上のように、kv 言語の先頭が、インデントなしで、始まっていないと出力できませんでした。
このように、kv 言語をロードする方法は色々、様々なサンプルコードを見てみても、使っている方法は、人によっても違うようです。
しかし、私は、諸事情により、基本的には、3つ目の方法をとっていく方針です。事情というのは、私のパソコンでは、.kv のファイルを開く際に、多少手間がかかるという程度のことです。
kv 言語を学ぶ
という事で、ロード方法はわかったところで、kv 言語について、詳しくみていきましょう。まず、前触れという事で、言っておきますと、私にとっては、かなり複雑で、理解するために、かなり時間を費やしました。主に、参考にさせてもらったサイトは、公式サイトとこちらのサイトです。
わからないままでも使えるのは確かです。以前の tkinter でも、そうだったのかもしれません。しかし、それでは、Python3 をマスターということには、なりませんよね。
まず、kv 言語で重要になってくる、初心者を困らせる単語が、多々あります。
- class ルール
- root ルール
- ウィジェット/子ウィジェット
- ……(などなど)
確かに、これを理解している人は、簡単かもしれませんが、正直にいって、私にはどれもわかりませんでした。英語の時間に、知らない単語が出てきて、頭がパンク……そんな状況です。
しかし、その理由として、それらをある程度知っている前提としているのが、痛いところです。しかし、なんだかんだ、時間を費やせば、わかってくるものです。
ルール とは
まずは、二つある class ルールと root ルールからです。ルールと付くからには、なんらかの決まりなのですが、これは、簡単に言えば、どのように表示するか(カスタマイズするか)を指定するものです。
しかし、なぜそれが二つもあるのでしょうか?class ルールは、クラス全体にルールが反映されます。つまり、あるクラスの中に、三つのウィジェットが存在した場合、その三つが全て、そのルールに従うのです。
対して、root ルールは、それぞれのウィジェットとその子ウィジェットにのみ反映されます。つまり、三つのウィジェットそれぞれに、それぞれの root ルールが存在するということになります。
ここで、子ウィジェットなのですが、簡単に言えば、ウィジェットの中のウィジェットです。例えば、配置用のウィジェットで指定した位置に、ボタンやラベルのようなウィジェットを配置する場合は、それらが子ウィジェットとなります。
ここで、子ウィジェットなのですが、簡単に言えば、ウィジェットの中のウィジェットです。例えば、配置用のウィジェットで指定した位置に、ボタンやラベルのようなウィジェットを配置する場合は、それらが子ウィジェットとなります。
そして、その表記を区別するために、class ルールは、<class 名>: のように、半角の山括弧と:(半角コロン)をつけ、root ルールの場合は、括弧なしの、root 名: のように、:半角コロンのみで、表記します。
kv 言語を使用する場合としない場合を比べてみると、わかりやすいかもしれません。コード自体に特に意味はありません……まずは、kv 言語を使用しなかった場合をみていきましょう。
1 # kv 言語を使用しない場合 2 from kivy.app import App 3 4 # 各ウィジェットをインポート 5 from kivy.uix.widget import Widget 6 from kivy.uix.boxlayout import BoxLayout 7 from kivy.uix.label import Label 8 9 class MyApp(App): 10 def build(self): 11 # インスタンスの作成 12 root = Widget() 13 box = BoxLayout(orientation='vertical') 14 15 # add_widget を使って、box に子ウィジェット(二つのラベル)を作成 16 box.add_widget(Label(text="Hello")) 17 box.add_widget(Label(text="World")) 18 19 # さらに、box ウィジェットを root ウィジェットの子ウィジェットに 20 root.add_widget(box) 21 return root 22 23 if __name__ == '__main__': 24 MyApp().run()
ここでは、Widget というウィジェットを使っていますが、空のウィジェットという認識で構わないです。つまり、12 行目では、ただ root というウィジェットを入れるためのインスタンスを作成したということです。なので、いきなり root を FloatLayout のインスタンス化しても良いのです。
次に、kv 言語を使った場合をみていきましょう。
1 # kv 言語を使用しない場合 2 from kivy.app import App 3 4 # 各ウィジェットをインポート 5 from kivy.uix.widget import Widget 6 from kivy.uix.boxlayout import BoxLayout 7 from kivy.uix.label import Label 8 9 10 # Widget を継承した MyWidgets クラスを作成 11 class MyWidgets(Widget): 12 pass 13 14 class MyApp(App): 15 16 def build(self): 17 return MyWidgets() 18 19 if __name__ == '__main__': 20 MyApp().run()
my.kv ファイル内
<MyWidgets>: BoxLayout: orientation: 'vertical' Label: text: "Hello" Label: text: "Hello"
kv ファイル内をみてもらうと、MyWidgets クラスに対して、class ルールが適用されていますね。そして、BoxLayout と Label には、それぞれの root ルールが存在しています。
kv 言語を使った場合の方が、視覚的にわかりやすいですね。しかし、どちらがいい、悪いということはありません。コードが長くなっていくにつれて、kv 言語の使用は便利になっていくかもしれませんね。
ちなみに、どちらのコードを実行しても、下のように表示されます。

最後に
個人的に、今回の kv 言語の理解は大変でした。知らない考え方に加えて、わからない言葉が多々、説明も少なく、調べに調べてこの結果です。英語と日本語、両方で調べることができるって意外と便利ですね。
次回からは、実際のコードをみながら、どのように Kivy のコードが書かれているかを見ていきたいと思います。読んでいただきありがとうございます。