Kv Languageを使ったKivyの動かし方

2019年12月5日

みなさまおはこんばんにちは、せなです

今回はPython3のGUIライブラリ「Kivy」の使い方をKv Languageを使って解説したいと思います

始めに

Kivyは数あるPythonのGUIライブラリの中でもデザイン性に富んだGUIです

KivyにはKv Languageという独自の言語が存在します
こちらの言語を習得する必要があるためほかののGUIライブラリと比較しても習得難度が高いのが欠点です

また、Kivyはマルチプラットフォームに対応(Windows, Mac, Linux, Android, IOS)しています
一度コードを書いてしまえば複数のプラットフォームで利用できるので簡単に開発することができます

環境

Windows 10
Python 3.7(Python 3.8未対応)
Kivy 1.11.1

メイン画面の表示

Kivyでメインとする画面を表示させるにはAppをインポートしてApp.run()と記述する必要があります
以下を実行すると、何も表示されていない画面が表示されます

kivytest.py

from kivy.app import App


class TestApp(App):
    pass


if __name__ == '__main__':
    TestApp().run()

これで何も表示されていない画面が作成できました

ラベルの表示

ラベルなどのウィジェットを表示するにはkvファイルを作成して行います
Python内に直接書き込むこともできますが、基本的にはKv Languageを使った方がいいと思います

ウィジェットについて知りたい方は以下の記事を参考にしてみてください

リンク:Kivyのウィジェットについて~Widgetの一覧~

kvファイル名はclass名のAppより前を小文字にして設定します
※ここを間違えるとkvファイルが読み込まれませんので注意しましょう

kivytest.py

変更なし

test.kv

Label:
    text: 'Hello Kivy'

kvファイルは「変数: 値」の形式で記述します
ウィジェットの要素を記述する時には改行とインデントが必要になります

上のkvファイルをPythonコードでの直書きに直すと
(Label(text='Hello World'))」と同じ内容になります

ボタンの使いかた

ボタンを使用する時にもkvファイルに書き込みます

以下はボタンをクリックすると元のテキストが変更されるコードとなります
長くなりますので、説明は後述します

kivytest.py

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import StringProperty


class TextWidget(Widget):
    text = StringProperty('')

    def __init__(self, **kwargs):
        super(TextWidget, self).__init__(**kwargs)
        self.text = 'default'

    def onButtonClick(self):
        self.text = 'Hello Kivy'


class TestApp(App):
    def __init__(self, **kwargs):
        super(TestApp, self).__init__(**kwargs)
        self.title = 'KivyTest'


if __name__ == '__main__':
    TestApp().run()

test.kv

TextWidget:

<TextWidget>:
    BoxLayout:
        orientation: 'vertical'
        size: root.size

        Label:
            id: label
            text: root.text

        Button:
            id: button
            text: "OK"
            on_press: root.onButtonClick()

追加箇所を一つずつ説明したいと思います

まずpythonコードから

from kivy.uix.widget import Widget
class TextWidget(Widget):

Widgetはkvファイルで追加したカスタムウィジェットを認識させるために必要です
そのためWidgetを継承したTextWidgetクラスを宣言しておく必要があります

from kivy.properties import StringProperty
text = StringProperty('')

StringPropertyはkivyのオブジェクトプロパティです
上のコードだと「text」を文字列のオブジェクトとして設定します
そのため数値などを扱おうとするとエラーになります

数値を扱いたい場合にはNumericPropertyを使用します

ほかにも複数の種類がありますので気になる方は以下のリンク先を参考にどうぞ

リンク:Kivyプロパティ入門

次にkvファイル

TextWidget:

<TextWidget>:

TextWigetはPythonコードでも、書いてありますがカスタムウィジェットを使用するのに必要な物です
kvファイルで記述しているだけだとエラーになります

BoxLayout:
        orientation: 'vertical'
        size: root.size

BoxLayoutはKivyに用意されているレイアウトの一つです
ほかにもいくつかレイアウトはありますので、詳しくは以下のリンクをご参考ください

orientationには「vertical」(縦並び)以外にも「horizontal」(横並び)があります

「size: root.size」はレイアウトのサイズを「root」つまり「TextWidget」のサイズと同じに設定します

リンク:Kivyレイアウト

on_press: root.onButtonClick()

on_pressはボタンをクリックしたときの挙動を指示します
上の場合はTextWidget内のonButtonClickを実行します

入力ボックス

以下は入力ボックスを作成して画面に表示させるコードとなります

kivytest.py

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import StringProperty


class TextWidget(Widget):
    text = StringProperty('')

    def __init__(self, **kwargs):
        super(TextWidget, self).__init__(**kwargs)
        self.text = 'No Text'

    def onButtonClick(self):
        self.text = self.ids.textInput.text


class TestApp(App):
    def __init__(self, **kwargs):
        super(TestApp, self).__init__(**kwargs)
        self.title = 'KivyTest'


if __name__ == '__main__':
    TestApp().run()

test.kv

TextWidget:

<TextWidget>:
    BoxLayout:
        orientation: 'vertical'
        size: root.size

        Label:
            id: label
            text: root.text

        Button:
            id: button
            text: "OK"
            on_press: root.onButtonClick()

        TextInput:
            id: textInput
            text: ''
            hint_text: 'Input Text'

追加・変更箇所を簡単に説明します

self.text = self.ids.textInput.text

「self.ids」ですがこれは参照オブジェクトとなります
ids.の後ろに書いている「textInput.text」はkvファイルの「id: textInput」の「text: "」の値を取得しています

self.idsを使用するとStringPropertyのようなオブジェクトプロパティを使用しなくてもよく簡潔に記述できます
ですが、self.idsを使用するよりもオブジェクトプロパティを使用した方が、より高速に動作します

参考までに以下のリンクにself.idsについてのより詳しい使い方などが書いてあります

リンク:PythonコードからKv langのWigetsへアクセスする方法

hint_text: 'Input Text'

「hint_text」は入力ボックスに未入力の時に表示されるテキストです

最後に

Kivyは日本語の資料が圧倒的に少ないせいか結構苦労しました
有志の方が作成されているKivyの日本語サイトには本当にお世話になりました
(これからもお世話になります)

Kivy公式サイト( https://kivy.org/doc/stable/
Kivy日本語翻訳サイト(https://pyky.github.io/kivy-doc-ja/

Kivyは難しいですが、Tkinterとかよりも触っていて楽しいので今後も記事にしていけたらなと思っています

ここまで読んで下さり、ありがとうございました
ではでは~