LoginSignup
516
632

More than 3 years have passed since last update.

Python Kivyの使い方① ~Kv Languageの基本~

Last updated at Posted at 2017-02-01

あらまし

PythonのGUIライブラリーを作るKivy(https://kivy.org/#home) ですが、日本では知名度はさほどではありません。理由として一番多いのはインストールしたのは良いが日本語でまとまった情報があまりなく、どう使用していいかわからないという声をよく聞きます。またKivyにはレイアウトを記述する際にPythonによるコード入力とは別にKv Languageと呼ばれる、CSSに似たKivy独時の言語を用いてレイアウトを作成できますが、情報が少なく慣れるまで時間がかかります。
ここではKv Languageを用いた簡単なプログラムを紹介してKv Languageの基本的な使い方を紹介します。

今回作成するプログラムについて

今回作成するプログラムは以下になります。

result.jpg

画像左端が起動直後の状態です、下にある「朝」、「昼」、「夜」のボタンをクリックすることでそれぞれ、「おはよう」、「こんにちは」、「こんばんは」の文字が表示されます。
内容としては、Kv Languageによるレイアウトの仕方とボタンをクリックした際の機能の実行の仕方の紹介です。

参考資料

資料ですがKivyの公式マニュアル(https://kivy.org/docs/ ) のProgramming Guideから「Kivy Basics」から「Kv Language」 の内容になります。ただし英語で書かれており理解が難しいので有志が翻訳した非公式※の日本語に翻訳(https://pyky.github.io/kivy-doc-ja/ ) したものを引用します。
※本家のサイトに事前に連絡して翻訳作業自体は問題がないことを確認しております。

追記:APIリファレンスの「Kv Language」を翻訳しましたのでこちらも一読されるとおすすめです。

Pycon JP 2017に登壇したさいのコードの解説をしました。こちらはKivyの全体的な説明をしていますので、Kivyで何ができるかの参考になります。

2017年12月追記:
日本語ですごく良い入門記事が書かれたので紹介します。
Kivyを始める際には一度目を通すことをお勧めします。

2018年10月追記:
Kivyでアプリを作られた方がいましたので紹介します

半年かけてファイル選択のデスクトップアプリアプリを作られた過程とソースコードを紹介されております。 RecycleView を使っての実装もされておりますのでKivyでどんなアプリができるかの参考になるかと思いますので一読されるのをお勧めします。

プログラムについて

Kivyを使用したコードの書き方ですが、色々な書き方があります。あくまでもこれは一例です。また、今回の記事を書く際に使用したソースコードをGithubに挙げております。ただし、fontや画像などの素材は配置しておりませんので必要な際はご自分で用意して配置してください。

検証環境

検証環境は以下の通りです。

  • OS: Windows10 64bit
  • Kivy:1.9.1
  • Python3.4※

※Python2系でもコードは実行できますが、日本語表示の箇所でエラーになります。その際は、コードを変更してみてください。(例:'日本語'→u'日本語')

エディターについて

Visual Studio code でKv言語に対応した拡張があります.

Python Kivyの使い方の一覧について

続き物として以下の投稿をしています。実際のアプリの作り方になります。

実際の説明

以下、実際にコードと結果を載せていきます。

1.空の画面を表示する

実行結果

WS000000.JPG

コード

main.py
#-*- coding: utf-8 -*-

from kivy.app import App

App().run()

Kvファイル

今回は使用しません

解説

Kivyの基本的な仕組みは Programming Guide(翻訳済み) » Kivy Basics(翻訳済み)を参考にしてください。

ここでは、Appクラスは、Kivyアプリを作成するための基本になるクラスです。
基本的な使い方は自分のアプリを作るときにAppクラスを継承してサブクラスを作り、そのラベルやボタンなどを追加することを覚えていれば十分です。

2.Appおよびラベルの表示

実行結果

out.jpg

コード

main.py
#-*- coding: utf-8 -*-

from kivy.app import App
from kivy.uix.label import Label

class TestApp(App):
    def build(self):
        return Label(text='Hello World')

TestApp().run()

Kvファイル

今回は使用しません

解説

Appクラスを継承してTestAppクラスを作成しました。
さらにbuild関数を実行して、作成時にLabel()を返すようにしました。
実行すると、画面中央に「Hello world」の文字が表示されたラベルが画面全体に作成されてます。
Label()はKivyのwidget( グラフィカルユーザインタフェースを構成する部品要素、およびその集まり)の一つです。Kivyはパーツ、レイアウトなどのwidgetを組み合わせてGUIを作成します。

またウィンドウの右上のタイトルに「Test」と表示されています。kivyではタイトルはAppクラスを継承したサブクラスの名のうちAppの前までの名前が表示されます。(例:TestApp→Testが表示されます)

さらに詳しく知りたい方はAPIリファレンス(英語)を参考にしてください。

3.Appおよびラベルの表示(Kv Languageを用いたもの)

実行結果

WS000002.JPG

コード

main.py
#-*- coding: utf-8 -*-
from kivy.app import App

class TestApp(App):
    pass

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

Kvファイル

test.kv
Label:  # add comment
    text: "Hello World"

解説

2と違うのは、main.py側ではサブクラスTestAppを作成しただけで、内部では何もしていません。代わりに新規にtest.kvというKv(Kivy language)ファイルを新規に作っています。KvファイルですがkivyではタイトルはAppクラスを継承したサブクラスの名のうちAppの前までと同じ先頭が小文字のファイル名が対応します。ここではサブクラス名がTestAppなので、test.kvが対応します。

Kivy languageですが次の特徴を持っています。

  • htmlのCSSによく似ています。
  • 書き方としては、追加する値、クラスに関して、<変数名or関数名>: <値> と書きます。「:」ですが前の<変数名>との間にはスペースを開けないでください
  • Pythonと同じくインデントでスペースまたはタブでできます。注意するのはインデントはファイルの頭から最初に見つけたスペースの数またはタブの数できまります。例えば、kvファイルの頭で半角スペース一文字を入れて改行すると、以降インデントは半角スペース一文字に設定されますので、半角スペース4文字でインデントを付けるとエラーになります。
  • 「#」でコメントを付けられます。pythonのように'''<コメント>'''は不可です

今回は、test.kv内で

Label:  # add comment
    text: "Hello World"

と宣言することで、Pythonファイル内でLabel()関数のtext引数に"Hello world"を指定して実行(Label(text='Hello World'))したことと同じになります。

Kv Languageについては、ここでも解説しますがProgramming Guide(翻訳済み) » Kv language(翻訳済み)を一読することをお勧めします。

参考

[Note] Kv Languageの使用について

Kv Languageを使用しなくても、他のGUIライブラリーのようにPythonでコードを書いてレイアウトを作成する事は可能です。日本でもPythonコードのみでも書かれている方もいます。

ただしKv Languageを使用することでレイアウトと機能の記述を分けることができます。これにより機能追加などをしたい場合やレイアウトの変更をしたい場合にコードの理解がしやすくなります。例えばアプリを作成して、ユーザーに配布した場合、機能の変更がないがレイアウトの変更をしたいという場合には、kvファイルをユーザーが直接変更してレイアウトを自分好みに変更することも可能です。

[Note] Kv Languageを書くファイルについて

Kv Languageですが、どのファイルに書くかですが3つのパターンが選べます。

  1. Pythonファイルに直書きする  
  2. Appのサブクラス名に対応したkvファイル(拡張子.kv)を作成して記述する
  3. Pythonファイル内で対応するKvファイルを指定して、そのKvファイルを記載する

1のPythonファイルに直書きする方法ですが、Builderクラスをimportして記述します。書き方は以下の通りです。

from kivy.lang import Builder
Builder.load_string("""
<App名>:
内容
""")

2の方法はすでに取り上げいるので省略します。
3のPythonファイル内で対応するKvファイルを指定する方法ですが、書き方は以下の通りです。

from kivy.lang import Builder
Builder.load_file('file.kv')

この場合file.kvがそのPythonファイルに対応するKvファイルになります。
通常は1か2の方法を用いて記述することが多いです。
1と2のどちらがいいかはケースバイケースかと思います。

参考

また、今回は取り上げませんがKvファイルをwidghtの名前と同じ名前のkvファイルを作成することで複数ファイルに分割することも可能のようです。(未検証)(間違いでした)

「#:include [force] 」をKvファイルで使用すること分割できるそうです。詳しくは以下を参照してください。

[Note] Kv Languageのプレビューツールについて

2017/07/14t追加

Kvファイルを書いて、結果を実行して確認するのは結構手間がかかるかと思います。1.10からkvファイルの変更をリアルタイムで反映する「kviewer」というツールが追加されました。導入の仕方や詳しい使い方は以下の記事を参考にしてください。

参考

4.複数のラベルの表示

実行結果

WS000004.JPG

コード

(3.の内容と変更はありません。)

Kvファイル

Kv Languageは以下になります。

test.kv
BoxLayout:
    Label:
        text: "Good Morning"
    Label:
        text: "Hello"
    Label:
        text: "Good Evening"

解説

今回は、Labelを3つ作成して横に等間隔に並べています。レイアウトの設定に「BoxLayout」を使用しています。kivyにはwidgetを並べるためのレイアウトがいくつか用意されてます。
「BoxLayout」は複数のwidgetを縦または横にならべるためのレイアウトです。

公式マニュアルから転載
boxlayout.gif

Kivyはこのレイアウトを一つまたは複数を使用することでレイアウトを作成していきます。
レイアウトの種類ですがBoxLayoutの他に「FloatLayout」、「RelativeLayout」、「GridLayout」、「PageLayout」、「ScatterLayout」、「StackLayout」がありますがまずは「BoxLayout」でレイアウトを作成することをお勧めします。

参考

5.複数のラベルの表示(縦並びにする)

実行結果

WS000005.JPG

コード

(3.の内容と変更はありません。)

Kvファイル

Kv Languageは以下になります。

test.kv
BoxLayout:
    orientation: 'vertical'     # 'horizontal'だと横一列

    Label:
        text: "Good Morning"
    Label:
        text: "Hello"
    Label:
        text: "Good Evening"

解説

4の場合はラベルは横に等間隔に並んでいましたが、今回は縦に3つ並んでいます。前との違いはKvファイルにorientation: 'vertical'の記述がある点です。
orientationはBoxLayoutのオプションの一つでwidgetの並びを設定します。値は2種類あり、「horizontal」だと横一列、「vertical」だと縦一列にwidgetの並びが設定されます。4の場合にorientationの記載がないのに横一列に並んでいるのはorientationのデフォルトの設定が「horizontal」になっているためです。

[Note] Kivyの座標系について

今回の並びをみているとわかるのですが、Kivyの原点座標は左下になります。これがKivyのとっつきにくい点の一つになっています。慣れると問題がないのですが、多くのGUIのソフトと違いKivyは原点が左下にあると覚えておいてください。

6.サイズの調整

実行結果

WS000006.JPG

コード

(3.の内容と変更はありません。)

Kvファイル

Kv Languageは以下になります。

test.kv
BoxLayout:
    orientation: 'vertical'     # 'horizontal'だと横一列

    Label:
        text: "Good Morning"
        size_hint_y: 0.5
    Label:
        text: "Hello"
        size_hint_y: 1
    Label:
        text: "Good Evening"
        size_hint_y: 2

実行結果は以下の通りです。

解説

size_hint_y: <値>を新たにパラ―メータに加えています。それによりLabelの位置が変わっています。size_hint_xに値を加えることでx方向の大きさを、size_hint_yに値を加えることでy方向の大きさが変わります。デフォルトでは両方とも1に設定されています。
大きさは画面全体の大きさ分の各比率になります。
例として今回の場合は"Good Morning"のラベルのサイズですが、
Y方向の比率 = (Good Morningの値)/(全部のsize_hintの値)=0.5/(0.5+1+2)=14%
になり、画面全体で14%のサイズになります。

size_hint以外に、座標を画面の比率から設定するpos_hintという設定もあります。ちなみにKivyでは座標を比率ではなく座標で指定することもできますがあまり推奨されていません。理由は画面サイズを自由に変更できるためにwidgetを座標で指定すると位置が固定のためにきれいに表示されないからです。

Kivyで位置を指定に関しては色々な指定方法がありますが、基本はsize_hintとpos_hintを使用して設定すれば問題がないです。pos_hintは今回は取り上げないので興味のある方は実際にコードを書いてみて試してみてください。

hintの有効な値ですがマニュアルをみると0.1~1が有効な範囲となっていますが、実際にコードを書くとわかるのですが、値を10や100といれても有効に機能していますので、マニュアルかKivy内部の実装のどちらかがあっていないようです。

7.サイズの調整2

実行結果

WS000007.JPG

コード

(3.の内容と変更はありません。)

Kvファイル

Kv Languageは以下になります。

test.kv
BoxLayout:
    orientation: 'vertical'     # 'horizontal'だと横一列

    Label:
        text: "Good Morning"
        size_hint_y: 0.5
    Label:
        text: "Hello"
        size_hint_y: 1
    Label:
        text: "Good Evening"
        size_hint_y: 0.5

解説

6の場合と値を変えてみました。

8.文字の色とラベルの色の変更

実行結果

WS000008.JPG

コード

main.py
#-*- coding: utf-8 -*-

from kivy.app import App


class TestApp(App):

    def __init__(self, **kwargs):
        super(TestApp, self).__init__(**kwargs)
        self.title = 'greeting'    # ウィンドウの名前を変更

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


Kvファイル

test.kv
BoxLayout:

    Label:        
        text: "Good Morning"
        color: 1,0,1,1
        size_hint_x: 0.5
    Label:
        text: "Hello"
        color: 0,1,0,1 # rgba
        size_hint_x: 1

        canvas.before:
            Color:
                rgba: 0, 1, 1, 1
            Rectangle:
                pos: self.pos
                size: self.size
    Label:
        text: "Good Evening"
        color: 0,0,1,1 # rgba
        size_hint_x: 0.5

解説

Python側ではTestAppクラスの初期化の際に以下のコマンドを入れています。

self.title = 'greeting'    # ウィンドウの名前を変更

こうすることで起動時のwindowの左上に表示されるタイトル名を変更することができます。

参考

また、Kvファイルですが、Labelに「color」のパラメータを新たに追加しています。「color」は文字の色のパラメータですとる値は[r(赤色),g(黄色),b(青色),a(透明度)]のリスト構造です。有効な値の範囲は0~1です。
Kivyでは色を指定するのに他にもHSVモードなど色を指定するいくつかの方法がありますが、
色を表示するのはcolorを使うことを覚えていれば十分です。
またLabelの背景の色を変更するですが、これは以下のコードで実現しています

        canvas.before:              #①
            Color:                        #②
                rgba: 0, 1, 1, 1
            Rectangle:                #③
                pos: self.pos     
                size: self.size 

① canvasコマンドで色をつけます。beforeはここでは詳しく説明しません、canvasに関しては Programming Guide(翻訳済み) » Graphics (翻訳済み)を読んでください。
②に関しては(R,G,B,A)= (0,1,1,1)で色を付けます。Labelと違うのは冒頭のCが大文字であることに注意してください。
③Rectangleは矩形(四角形)を表示するコマンドです。posパラメータは表示する座標、sizeは描画する範囲の幅と高さを指定しています。ここでposとsizeの値にselfを使用していますが、selfはKvの予約語でそのWidgetを取得するのに使用します。今回はHelloを表示するLabel内ですので、self.posはLabelのxy座標、self.sizeはそのLabelの幅と高さの値を指しています。
これにより、Helloを表示するLabelの座標と幅と高さ分の(0.1.1.1.1)の色の四角形を描画できます。図形は四角形の他にも三角形、円、線を描くことができます。

参考

[Note] Kvの予約語について

Kivy Languageにはあらかじめシステム上で使用が決められている予約語がいくつかあります。代表的なものは以下の物があります。

  • self ・・・ そのWidgetを取得
  • root ・・・ rootWidgetを取得
  • app ・・・ Appを取得

Kvファイルの予約語から引用

参考

9.ボタンの追加

実行結果

WS000010.JPG

コード

(8.の内容と変更はありません。)
2018/02/03追加:ネット上でご指摘がありました。8.のままだとエラーになります。

main.py
#-*- coding: utf-8 -*-

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

from kivy.properties import StringProperty 

class TextWidget(Widget):
    pass

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

    def build(self):
        return TextWidget()

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


Kvファイル

Kv Languageは以下になります。

test.kv
TextWidget:

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

        # ラベル
        Label:
            id: label1
            font_size: 68
            text: "Hello World"

        Button:
            id: button1
            text: "OK"
            font_size: 48

解説

新たにButtonを追加しました。ButtonはLabelのサブクラスなのでLabelで使用していたパラ―メータも使えます。今回のプログラムは起動してOKボタンをクリックしてもクリック時にボタンの色が変わるだけで何も起きません。ここで出来たのはあくまでもLabelとButtonを使用したレイアウトができただけでボタンに対して何らかのアクション(Event)を起こした際の動作を登録しておりません。動作の登録に関しては次の項目で説明します。
またfont_sizeは表示される文字のサイズになります。デフォルトでは15になっていますが、それだと表示サイズが小さかったので大きくしました。

またwidgetごとに新たにidというパラ―メータを追加していますが今回はふれません。参考の項目で使用方法を説明します。

2018/02/03追加:今回、カスタムウィジェットであるTextWidgetを追加して、そこにButtonなどの既存のWidgetを追加しています。カスタムウィジェットはKvファイルで追加しただけではエラーになります。理由はTextWidgetが何なのかKivyで解決できないためです。そのめPythonファイル側でwidgetクラスを継承したTextWidgetクラスを宣言する必要があります。

10.ボタンを押した場合の機能の追加

実行結果

WS000012.JPG

コード

コードは以下の通りです。

main.py
#-*- coding: utf-8 -*-

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 = ''

    def buttonClicked(self):        # ボタンをクリック時
        self.text = 'Hello World'


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

    def build(self):
        return TextWidget()

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


Kvファイル

Kv Languageは以下になります。

test.kv
TextWidget: # ルートに追加

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

        # ラベル
        Label:
            id: label1
            font_size: 68
            text: root.text    # root(TextWidget)の変数テキストの値を取得

        Button:
            id: button1
            text: "OK"
            font_size: 68
            on_press: root.buttonClicked()  # ボタンをクリックした時にpython側の関数を呼ぶ

解説

プログラムを実行すると、起動時にはラベルには何も表示されませんが、OKボタンをクリックすると、「Hello World」の文字がラベルに表示されます。
まずpython側のコマンドですが、

from kivy.properties import StringProperty 

としてkivy.propertiesからStringPropertyをimportしています。
kivyのpropertiesはボタンが押された場合などのイベントが実行された場合のオブジェクトの属性に値の変更があった場合に実行する仕組みの事です。今回はボタンが押されたときに、ラベルの文字が変化するのに使用します。プロパティですが、文字列や数字、辞書型ごとに型があります。型としては以下があります。

  • StringProperty
  • NumericProperty
  • BoundedNumericProperty
  • ObjectProperty
  • DictProperty
  • ListProperty
  • OptionProperty
  • AliasProperty
  • BooleanProperty
  • ReferenceListProperty

プロパティの詳細はProgramming Guide(翻訳済み) » Events and Properties(翻訳済み)を参考にしてください。
実際のコード上ではこの後、TextWidgetクラスでクラス変数textを宣言しておりそこでStringProperty() を代入しています。その後、「init」メソッドではtextには空白を代入しており、buttonClicked()関数を作成して、その中でtextに「Hello World」の文字を代入しています。

class TextWidget(Widget):
    text = StringProperty()    # プロパティの追加

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

    def buttonClicked(self):        # ボタンをクリック時
        self.text = 'Hello World

一方、kvファイルですが、ラベルとボタンで以下のようになっています。


        # ラベル
        Label:
            id: label1
            font_size: 68
            text: root.text    # root(TextWidget)の変数テキストの値を取得

        Button:
            id: button1
            text: "OK"
            font_size: 68
            on_press: root.buttonClicked()  # ボタンをクリックした時にpython側の関数を呼ぶ

まずLabelのtextパラメータには、root.textが設定されています。rootはKv Languageの予約語でrootウィジェットを指しています。ですのでここではTextWidgetのクラス変数textを指しています。

またButtonではon_pressというパラ―メータが追加されています。on_pressはあらかじめKivyで用意されているイベントでButtonを押した際に実行されるイベントです。この場合は、 root.buttonClicked()を設定して、これによりOKのボタンが押されたときにTextWigetのbuttonClicked()が実行されます。

Buttonのイベントにはこのほかには「on_release」がありこちらはボタンが離された場合に実行されるイベントになります。

参考

11.複数のボタンを追加した場合

実行結果

起動時
WS000013.JPG

moriningをクリック
WS000014.JPG

dayをクリック
WS000015.JPG

nightをクリック
WS000016.JPG

コード

コードは以下の通りです。

main.py
#-*- coding: utf-8 -*-

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 = ''

    def buttonClicked(self):
        self.text = 'Good morning'

    def buttonClicked2(self):
        self.text = 'Hello'

    def buttonClicked3(self):
        self.text = 'Good evening'


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

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

Kvファイル

Kv Languageは以下になります。

test.kv
#-*- coding: utf-8 -*-


TextWidget: # ルートに追加

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

        # ラベル
        Label:
            id: label1
            font_size: 68
            text: root.text

        BoxLayout:
            Button:
                id: button1
                text: "morning"
                font_size: 68
                on_press: root.buttonClicked()  # ボタンをクリックした時

            Button:
                id: button2
                text: "day"
                font_size: 68
                on_press: root.buttonClicked2()  # ボタンをクリックした時

            Button:
                id: button3
                text: "night"
                font_size: 68
                on_press: root.buttonClicked3()  # ボタンをクリックした時

解説

まずpythonファイル側ですが、こちらは前の内容から複数ボタンが押された場合の関数が追加されただけなので説明を省略します。

Kv Languageですがボタンを押した際の動作は前回に説明をしたので問題ないかと思います。問題はレイアウトのほうで、今回は以下の構造をしています

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

        Label:
        省略
        BoxLayout: #②
            Button:
   ~省略
            Button:
   ~省略
              Button:
        省略

BoxLayoutが2回使われていますが、まず①のBoxLayoutでorientationの 設定が「vertical」になっています。これにより画面が上下に2分割されたレイアウトができます。その後、Labelを追加して、上下分割された画面のうち上部に配置されます。問題は画面下の部分の方です。配置に際して②でBoxLayoutが配置されます。orientationのパラ―メータの設定がないですが、orientationはデフォルトで「horizonal」に設定されています。これにより、画面下部は横並びのレイアウトになり、今回はButtonが3つ追加されていますので、結果として横にボタンが3つ並べたレイアウトになります。
BoxLayoutを2つ組み合わせることにより、画面の上半分 は1つ、下半分は水平に3分割のレイアウトができます。
Kivyでは複数のLayoutを組み合わせることで複雑なレイアウトを設置することが可能になります。

12.レイアウトを変更

実行結果

実行結果は以下の通りです。

起動時
WS000017.JPG

moriningをクリック
WS000018.JPG

dayをクリック
WS000019.JPG

nightをクリック
WS000020.JPG

コード

11と変化ありません。

Kvファイル

Kv Languageは以下になります。

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

        # ラベル
        Label:
            size_hint_y: 0.7    # 画面全体の70%を表示するように調整
            id: label1
            font_size: 68
            text: root.text

        BoxLayout:
            size_hint_y: 0.3     # 画面全体の30%を表示するように調整
            Button:
                id: button1
                text: "morning"
                font_size: 68
                on_press: root.buttonClicked()  # ボタンをクリックした時

            Button:
                id: button2
                text: "day"
                font_size: 68
                on_press: root.buttonClicked2()  # ボタンをクリックした時

            Button:
                id: button3
                text: "night"
                font_size: 68
                on_press: root.buttonClicked3()  # ボタンをクリックした時

解説

Kvファイル側で size_hint_yを使用してサイズ調整をしています。上半分の、ラベルの縦のサイズが大きくなり、下半分のボタンのサイズが小さくなります。

13.クリック時の機能追加(文字の色を変更する)

実行結果

実行結果は以下の通りです。

起動時
WS000021.JPG

moriningをクリック
WS000022.JPG

dayをクリック
WS000023.JPG

nightをクリック
WS000024.JPG

コード

コードは以下になります。

main.py
#-*- coding: utf-8 -*-

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

from kivy.properties import StringProperty, ListProperty

class TextWidget(Widget):
    text  = StringProperty()
    color = ListProperty([1,1,1,1])

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

    def buttonClicked(self):
        self.text = 'Good morning'
        self.color = [1, 0, 0 , 1]

    def buttonClicked2(self):
        self.text = 'Hello'
        self.color = [0, 1, 0 , 1 ]

    def buttonClicked3(self):
        self.text = 'Good evening'
        self.color = [0, 0, 1 , 1 ]

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

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

Kvファイル

Kv Languageは以下になります。

test.kv
#-*- coding: utf-8 -*-


TextWidget: # ルートに追加

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

        # ラベル
        Label:
            size_hint_y: 0.7
            id: label1
            font_size: 68
            text: root.text
            color: root.color

        BoxLayout:
            size_hint_y: 0.3
            padding: 20,30,20, 10
            Button:
                id: button1
                text: "morning"
                font_size: 68
                on_press: root.buttonClicked()  # ボタンをクリックした時

            Button:
                id: button2
                text: "day"
                font_size: 68
                on_press: root.buttonClicked2()  # ボタンをクリックした時

            Button:
                id: button3
                text: "night"
                font_size: 68
                on_press: root.buttonClicked3()  # ボタンをクリックした時

解説

前回までのコードでラベルの表示する文字の色を変える機能を追加しています。
内容としてはPython側でTextWidgetクラスでクラス変数をcolor を新たにListPropertyで宣言して値を実現しています。colorはrgbaの複数の値を格納するためにListPropertyを使用しています。

14.日本語の表示(フォントの追加)

実行結果

実行結果は以下の通りです。

起動時
WS000025.JPG

朝をクリック
WS000026.JPG

昼をクリック
WS000027.JPG

夜をクリック
WS000028.JPG

コード

コードは以下になります。

main.py
#-*- coding: utf-8 -*-

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

from kivy.properties import StringProperty, ListProperty

from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path

# デフォルトに使用するフォントを変更する
resource_add_path('./fonts')
LabelBase.register(DEFAULT_FONT, 'mplus-2c-regular.ttf') #日本語が使用できるように日本語フォントを指定する


class TextWidget(Widget):
    text  = StringProperty()
    color = ListProperty([1,1,1,1])

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

    def buttonClicked(self):
        self.text = 'おはよう'
        self.color = [1, 0, 0 , 1]

    def buttonClicked2(self):
        self.text = 'こんにちは'
        self.color = [0, 1, 0 , 1 ]

    def buttonClicked3(self):
        self.text = 'こんばんは'
        self.color = [0, 0, 1 , 1 ]

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

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


Kvファイル

Kv Languageは以下になります。

test.kv

TextWidget:

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

        # ラベル
        Label:
            size_hint_y: 0.7
            id: label1
            font_size: 68
            text: root.text
            color: root.color

        BoxLayout:
            size_hint_y: 0.3
            padding: 20,30,20, 10
            Button:
                id: button1
                text: "朝"
                font_size: 68
                on_press: root.buttonClicked()

            Button:
                id: button2
                text: "昼"
                font_size: 68
                on_press: root.buttonClicked2()

            Button:
                id: button3
                text: "夜"
                font_size: 68
                on_press: root.buttonClicked3()

解説

Kivyですが、windowsではPython34\Lib\site-packages\kivy\data\fonts配下にフォントデータはありますが、デフォルトの文字コードはRobotoで、Robotoは欧文フォントなのでそのままでは日本語は正しく表示されません
なので日本語を表示するためには、自分で日本語を表示するフォントを使用する必要があります。Pythonコード側で

from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path

# デフォルトに使用するフォントを変更する
resource_add_path('./fonts')
LabelBase.register(DEFAULT_FONT, 'mplus-2c-regular.ttf') #日本語が使用できるように日本語フォントを指定する

としていますが、resource_add_pathはkivy内で読み込みパスを指定しています。
次にLabelBase.registerで標準に使用するフォントで日本語が表示できるフォントを指定しています。今回はpythonのファイルと同じ階層に「fonts」フォルダを作成しそこに「mplus-2c-regular.ttf」ファイルを配置しています。その「mplus-2c-regular.ttf」ファイルを文字を表示する際のフォントに指定しています。

日本語の表示するには大まかに分けて以下の2つの方法があるかと思います。

  • OSごとのシステムフォントで日本語が表示可能なフォントを指定する。
  • フォントを用意して起動時にデフォルトフォントを用意する。

OSごとのシステムフォントで日本語が表示可能なフォントを指定する方法ですが、kivyにはplatformという機能があり、これを使用すると実行時のOSを取得できます。これを用いてOSごとにデフォルトで表示するフォントを変更することができます。日本でも実際にやられている方がいます。

参考

ただし、このやり方だと未知のOSやAndroidなどの機種ごとのカスタマイズが多い機種だと指定したフォントが存在しない場合があります。

フォントを用意して起動時にデフォルトフォントを用意する方法はフォントファイル(.ttf)を用意して、プログラムと同封して起動時にそのフォントを使用するように設定します。今回はこのやり方を使用しています。フォントはM+というライセンスフリーなフォントを使用しています。
フォントの指定にはいろいろなやり方があり、いくつか紹介されていますので興味がある方は以下の箇所をのぞいてみてください。

2019/7/30更新
日本語表示用のパッケージを作成された方がいらしたので紹介します

Python: インポートするだけで Kivy が日本語を表示できるようになる japanize-kivy を作った

参考

Note Kvファイルの文字コードについて

kvファイルはWindowsではPython3系では「shift-jis」で2系の場合は「utf-8」で保存しないと正しく表示されません。

Note Appのtitleについて

Python2系だと「u'日本語'」で入力してもエラーになります。
エラーメッセージは以下の通りです。どうしたらよいかわかる方はご連絡ください。

File "c:\Python27\lib\site-packages\kivy\core\window\window_sdl2.py", line 332, in set_title
     self._win.set_window_title(title)
 TypeError: Argument 'title' has incorrect type (expected str, got unicode)

2017/2/4追記
コメントで教えていただいた内容で表示できました。
「title」を「u'日本語'」で表示した後、「main」を以下のようにすると実行できます。

import sys

if __name__ == '__main__':
     reload(sys)
     sys.setdefaultencoding('utf-8')
     TestApp().run()

参考
http://d.hatena.ne.jp/shu223/20111201/1328334689
http://blog.livedoor.jp/kaz0215/archives/51124286.html

15.起動時の解像度を変更およびパラメータの使いまわしについて

実行結果

実行結果は以下の通りです。

起動時
WS000029.JPG

コードは以下の通りです。

main.py
#-*- coding: utf-8 -*-
from kivy.config import Config
Config.set('graphics', 'width', '640')
Config.set('graphics', 'height', '480')

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

from kivy.properties import StringProperty, ListProperty

from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path

# デフォルトに使用するフォントを変更する
resource_add_path('./fonts')
LabelBase.register(DEFAULT_FONT, 'mplus-2c-regular.ttf') #日本語が使用できるように日本語フォントを指定する


class TextWidget(Widget):
    text  = StringProperty()
    color = ListProperty([1,1,1,1])

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

    def buttonClicked(self):
        self.text = 'おはよう'
        self.color = [1, 0, 0 , 1]

    def buttonClicked2(self):
        self.text = 'こんにちは'
        self.color = [0, 1, 0 , 1 ]

    def buttonClicked3(self):
        self.text = 'こんばんは'
        self.color = [0, 0, 1 , 1 ]

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

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



Kv Languageは以下になります。

test.kv


TextWidget:


<MyButton@Button>:
    font_size: 68

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

        # ラベル
        Label:
            size_hint_y: 0.7
            id: label1
            font_size: 68
            text: root.text
            color: root.color

        BoxLayout:
            size_hint_y: 0.3
            padding: 20,30,20, 10
            MyButton:
                id: button1
                text: "朝"
                #font_size: 68
                on_press: root.buttonClicked()

            MyButton:
                id: button2
                text: "昼"
                #font_size: 68
                on_press: root.buttonClicked2()

            MyButton:
                id: button3
                text: "夜"
                #font_size: 68
                on_press: root.buttonClicked3()

解説

画像だとわかりにくいですが、起動すると画面サイズが小さくなっているのがわかります。

from kivy.config import Config
Config.set('graphics', 'width', '640')
Config.set('graphics', 'height', '480')

Pythonファイルがわの冒頭で以下のコマンドが追加されています。
Kivyはインストール直後のデフォルトの設定では、解像度が800×600で起動するようになっています。Programming Guide(翻訳済み) » Configure Kivy(翻訳済み)に書いてありますが、Kivyには「config.ini」というファイルで基本的な設定はそこに記載されています。
Windowsでは*C:\Users<ユーザ名.kivy *配下にあります。「config.ini」の中身は以下のようになっています。

[kivy]
keyboard_repeat_delay = 300
keyboard_repeat_rate = 30
log_dir = logs
log_enable = 1
log_level = info
log_name = kivy_%y-%m-%d_%_.txt
window_icon = 
keyboard_mode = 
keyboard_layout = qwerty
desktop = 1
exit_on_escape = 1
pause_on_minimize = 0
config_version = 14

[graphics]
display = -1
fullscreen = 0
height = 600
left = 0
maxfps = 60
multisamples = 2
position = auto
rotation = 0
show_cursor = 1
top = 0
width = 800
resizable = 1
borderless = 0
window_state = visible
minimum_width = 0
minimum_height = 0

[input]
mouse = mouse
wm_touch = wm_touch
wm_pen = wm_pen

[postproc]
double_tap_distance = 20
double_tap_time = 250
ignore = []
jitter_distance = 0
jitter_ignore_devices = mouse,mactouch,
retain_distance = 50
retain_time = 0
triple_tap_distance = 20
triple_tap_time = 375

[widgets]
scroll_timeout = 250
scroll_distance = 20
scroll_friction = 1.
scroll_stoptime = 300
scroll_moves = 5

[modules]


このうち「graphics」の項目のheight とwidthの値が起動時の解像度になります。
このconfig.iniの中身を書き換えて変更することも可能ですが、それだと配布した際にユーザごとのconfig.iniの設定に依存することになりますので、このように一時的に変更することも可能です。

参考
Kivyで簡単なアプリを作ってみる

またこのやり方とは別に、windw()を使用して解像度を変更させる方法もあります。

from kivy.core.window import Window
#Window.size = (450, 600)

ただしこちらのやり方でAndroidなどのモバイルのデバイスで表示させると解像度がおかしくなるので、モバイルで表示させる場合はwindow()を使用しないか、以前に説明したpratformを用いてOSの種類によっては表示させないなどの処理が必要です。

またKvファイルですが以下のようになっています

<MyButton@Button>: # ①
    font_size: 68

<TextWidget>:
   ~省略
            MyButton: #②
                id: button1
                text: "朝"
                #font_size: 68
                on_press: root.buttonClicked()
            MyButton:
                id: button2
                text: "昼"
                #font_size: 68
                on_press: root.buttonClicked2()

            MyButton:
                id: button3
                text: "夜"
                #font_size: 68
                on_press: root.buttonClicked3()

前回との違いは、
①で「MyButton@Button」というwidgetが宣言されてるのと、②で前回までは「Button」が設定されていたところが「MyButton」に設定されています。kivyではwidget宣言時にwidget@widgetの種類と宣言することで@より後のwidgetの種類を継承することができます。今回は「Button」widgetを宣言することで「Button」widgetを継承した「MyButton」widgetを作成しました。MyButtonのなかでfont_sizeを設定することで、前回まで各Buttonでfont_sizeを個別に指定する必要がなくなり同一の値が使用できるようになります。
詳しくはProgramming Guide(翻訳済み) » Kv language(翻訳済み)を読んでみてください。

16.画像の表示

実行結果

実行結果は以下の通りです。

起動時
WS000033.JPG

コード

コードは以下になります。

main.py
#-*- coding: utf-8 -*-
from kivy.config import Config
Config.set('graphics', 'width', '640')
Config.set('graphics', 'height', '480')

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

from kivy.properties import StringProperty, ListProperty

from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path

# デフォルトに使用するフォントを変更する
resource_add_path('./fonts')
LabelBase.register(DEFAULT_FONT, 'mplus-2c-regular.ttf') #日本語が使用できるように日本語フォントを指定する


class TextWidget(Widget):
    text  = StringProperty()

    def __init__(self, **kwargs):
        super(TextWidget, self).__init__(**kwargs)
        pass

    def buttonClicked(self):
        pass

    def buttonClicked2(self):
        pass

    def buttonClicked3(self):
        pass

class TestApp(App):
    def __init__(self, **kwargs):
        super(TestApp, self).__init__(**kwargs)
        self.title = '画像表示'

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

Kv Languageは以下になります。

test.kv


TextWidget:

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

        Image:
            source: './image/sample2.jpg'


        BoxLayout:
            size_hint_y: 0.3
            padding: 20,30,20, 10
            Button:
                id: button1
                text: "サンプル1"
                font_size: 30
                on_press: root.buttonClicked()

            Button:
                id: button2
                text: "サンプル2"
                font_size: 30
                on_press: root.buttonClicked2()

            Button:
                id: button3
                text: "サンプル3"
                font_size: 30
                on_press: root.buttonClicked3()

解説

Kivyでは画像を表示することが可能です。

        Image:
            source: './image/sample2.jpg'

と指定することで画像を表示できます。またsizeパラメータを使用することで表示サイズを変更したりも可能です。今回はボタンをクリックしても画像は切り替わりません。ボタンクリックによる画像切り替えは次の項目で説明します。

参考

17.画像の表示(ボタンによる画像切り替え)

実行結果

実行結果は以下の通りです。

起動時 or サンプル1をクリック時
WS000000.JPG

サンプル2をクリック時
WS000001.JPG

サンプル3をクリック時
WS000002.JPG

コード

コードは以下の通りです。

main.py
#-*- coding: utf-8 -*-
from kivy.config import Config
Config.set('graphics', 'width', '640')
Config.set('graphics', 'height', '480')

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

from kivy.properties import StringProperty

from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path

# デフォルトに使用するフォントを変更する
resource_add_path('./fonts')
LabelBase.register(DEFAULT_FONT, 'mplus-2c-regular.ttf') #日本語が使用できるように日本語フォントを指定する

resource_add_path('./image')


class ImageWidget(Widget):
    source = StringProperty('./image/sample.jpg')
    #source = StringProperty(None)


    def __init__(self, **kwargs):
        super(ImageWidget, self).__init__(**kwargs)
        pass

    def buttonClicked(self):
        self.source= './image/sample.jpg'

    def buttonClicked2(self):
        self.source = 'sample2.jpg'

    def buttonClicked3(self):
        self.source = 'sample3.jpg'


class TestApp(App):
    def __init__(self, **kwargs):
        super(TestApp, self).__init__(**kwargs)
        self.title = '画像表示'

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

Kvファイル

Kv Languageは以下になります。

test.kv

ImageWidget:

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

        Image:
            source: root.source


        BoxLayout:
            size_hint_y: 0.3
            padding: 20,30,20, 10
            Button:
                id: button1
                text: "サンプル1"
                font_size: 30
                on_press: root.buttonClicked()

            Button:
                id: button2
                text: "サンプル2"
                font_size: 30
                on_press: root.buttonClicked2()

            Button:
                id: button3
                text: "サンプル3"
                font_size: 30
                on_press: root.buttonClicked3()

解説

説明ですが、前回までの内容を読まれると大体内容がわかるかと思いますので詳しい説明は省きますが、Python側でStringPropertyを用いてクラス変数sourceを作成して、ボタンクリック時にそこに画像ファイルのパスを切り替えて表示しています。
※2017/5/16追記,StringPropertyに"None"の宣言時にNoneを指定していると起動時には画像を何も指定していないので真っ白の画面が表示されます。

今回は画像は加工済みの画像を表示していますが、buttonClicked()の処理でPillowやOpenCVなどの画像ライブラリ―を用いてフィルタ―をかけて画像ファイルを生成し、その画像ファイルを生成するといった処理ができるかと思います。
なお、画像ファイルを生成せずにバイト列にして直接読み込むことも可能です。
その際はTextureのblit_buffer()を使用することで実現できます

2017/10/09 更新
別記事でOpenCVやPillowで読み込んだ画像をblit_buffer()で表示する方法の記事を書きました。

Python KivyでOpencvやPillowで画像を表示する方法

参考

まとめ

ここまでのことで、レイアウトの基本的な説明とボタンをクリックした際の動作の実行を説明しましたので簡単なアプリの実装はできるようになったかと思います。
ここまでの内容を読んで、公式マニュアルの翻訳サイトの「Programming Guide」を読み直すと色々な発見があると思いますので、一度通して読み直すことをお勧めします。

またKivyのサンプルプログラムですが、Kivyのexample配下には様々なサンプルがあるのでぜひ一度見てみるとよいと思います。
どういったプログラムがあるかは、Gallery of Examples(翻訳済み) » Gallery(翻訳済み)Getting Started(翻訳済み) » Examples(翻訳済み)に内容の説明があります。

Kivy自体は機能がたくさんありますがこれを読んで何か参考になれば幸いです。
また有志による公式マニュアルの翻訳もやっておりますので興味があれば参加してみてください。2017年はAPIを中心にやっていいこうと考えています。

参考 ファイルを選択する

Kivyでファイルを選択する際はFileChooserを使用してファイル選択ダイアログを開くことができます

実際の使用法ですが以下のサイトで、他の方が実際の使用法をコードとともに公開しているので参考にしてみてください。

参考

参考 日本語の入力について(注意)

以下はテキストボックスに文字を入れて「OK」ボタンをクリックするとラベルに入力された文字が表示されます。

実行結果

実行結果は以下の通りです。
result.jpg

コード

コードは以下の通りです。

main.py
#-*- coding: utf-8 -*-

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

from kivy.properties import StringProperty

from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path

# デフォルトに使用するフォントを変更する
resource_add_path('./fonts')
LabelBase.register(DEFAULT_FONT, 'mplus-2c-regular.ttf') #日本語が使用できるように日本語フォントを指定する


class TextWidget(Widget):
    text = StringProperty()

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

    def buttonClicked(self):
        self.text =  self.ids["text_box"].text


class TestApp(App):
    def __init__(self, **kwargs):
        super(TestApp, self).__init__(**kwargs)

    def build(self):
        return TextWidget()

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

Kvファイル

Kv Languageは以下になります。

test.kv
TextWidget: # ルートに追加

<TextWidget>:
    BoxLayout:
        orientation: 'vertical'
        size: root.size
        # ラベル
        Label:
            id: label1
            font_size: 68
            text: root.text

        BoxLayout:
            TextInput:
                id: text_box
                size_hint_x: 70
                font_size: 68
                focus: True
                on_text_validate: root.buttonClicked()
            Button:
                id: button1
                size_hint_x: 30
                text: "OK"
                font_size: 68
                on_press: root.buttonClicked()  # ボタンをクリックした時

解説

Textinput を使用すると、テキストを入力できます。

ただし問題があります。日本語の入力自体はフォントを日本語用のフォントを指定すればできます。コピー&ペーストで貼り付けもできます。問題はOSによってはIMEが開かないので文字が確定するまで全角文字が表示されないという問題があります。公式でも問題になっていますが、問題の経緯としては元々Kivyは文字入力をpygameというライブラリに依存しており、pygameの既知の問題でIMEが表示されないという問題がありました。その後、Kivy自体はpygameの依存をやめてSDLベースで色々な機能を書き直して、pygameを使用しないようにしてきました。
しかし、入力中(IME)の際にSDLから発行される「SDL_TEXTEDIT」イベントを受けて行う処理がKivy側にありません。そのため入力中の日本語が表示されません。

日本語入力を積極的に使用したい際は注意が必要です。現在のところOSごとのIMEに関してはこんな感じです。

[追記]2018年7月、Kivyの最新のバージョン(1.10.1)がリリースされました。こちらではIME表示の
内容のプルリクが採用されており、IMEが動作して入力中の日本語が表示されるようになりました。

2018年7月現在で日本語入力に関するPRが採択されたので状況が変わりました。

  • windows:可、IMEは開く
  • MacOS:可、IMEは開く
  • Linux:不可(?)。
  • Android:可、Nexus5で試したところ日本語入力は問題なくできます。
  • iOS:不可、IMEは開かないそうです。(未検証)

日本語入力中のIMEが開かない理由と、開く方法、環境構築の方法ついて記事を書きましたので以下を参考にしてみてください。

windowsでの日本語入力について

windowsについては非公式ですが変換中の候補まで出るコードを書いてDLLを作った方がいます。

ボタンをクリックした際のテキストの入力ですがそれは次の参考で説明します。

参考 kvファイルの値をPython側で取得する方法

「日本語の入力について(注意)」についてのコードを見るとTextInputは以下のコードになっています。

test.kv

<TextWidget>:
        BoxLayout:
            TextInput:
                id: text_box    # ★注目

ここで注目すべきは「id」に「text_box」と入力しています。
一方、Python側のコードですがボタンを押した際に呼ばれる関数buttonClicked()は以下のようになっています。

python.py
    def buttonClicked(self):
        self.text =  self.ids["text_box"].text

Kivyではidと場所のタグ付けがされている全てのウィジェットをself.idsという辞書型のプロパティで一か所で管理しています
そうすることでid名をキーにすることでそのウィジェットの各パラメータの値を取得できます。詳しくはProgramming Guide(翻訳済み) » Kv language(翻訳済み)の「PythonコードからKv lang の内部で定義されたwidgetsにアクセスする」の項目に記載されています。
ただし公式サイトのマニュアルですと、ObjectPropertyを使用して値を習得する方がより良い方法とされています。ObjectPropertyを使用して値を取得する方法は説明は手順が少し複雑なのと初心者向けではないので別の記事で説明します。

参考 Kivy側でPythonファイルの関数の呼び方

ここまでで、Python側のクラスのメソッド(関数)は、Kvファイル側で、「self」や「root」といった予約語を使うことで利用することができました。
では逆にPython側で書いたメソッドを呼びだして利用するにはどうしたらいいでしょうか。
方法としてはKvファイル内でPythonファイルをimportして利用する方法があります。

実行例

実行結果は以下になります。
WS000012.JPG

コード

pythonファイル(main.py)は以下になります。

main.py
#-*- coding: utf-8 -*-

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

from kivy.properties import StringProperty

def buttonClicked():    # この関数を呼び出します
    print("call def")
    text = 'Hello World'

    return text

class TextWidget(Widget):

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

    def buttonClicked(self):
        self.text = 'Hello World'


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

    def build(self):
        return TextWidget()

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

Kv Languageは以下になります。

test.kv
#: import main main
# ↑①main.pyをインポートします。

TextWidget: # ルートに追加

<TextWidget>:
    BoxLayout:
        id: input
        orientation: 'vertical'
        size: root.size
        l_text:'aa'

        # ラベル
        Label:
            id: label1
            font_size: 68
            text: input.l_text  # aaからクリック後、'Hello World'に表示が変わります

        Button:
            id: button1
            text: "OK"
            font_size: 68
            on_press: input.l_text = main.buttonClicked()  # ②main.pyの関数を呼び出します。

解説

test.kv
#: import main main
# ↑①main.pyをインポートします。


<TextWidget>:
    BoxLayout:

    省略           
        Button:
            id: button1
            text: "OK"
            font_size: 68
            on_press: input.l_text = main.buttonClicked()  # ②main.pyの関数を呼び出します。

①でmain.pyをimportしています。詳しい使用方法は以下になります

#: import <Kvファイルで使いたい名前> <importしたいライブラリorファイル名>

この書き方をすることでKvファイル側で特定のライブラリ、ファイル名を呼び出せます。
今回は①でmain.pyをmainという名前でimportした後に、②のOKボタンをクリック時にmain.pyのbuttonCliced()を呼び出しています。

参考

参考 GridLayoutの使いかた

KivyでGridLayoutを使用しようとしてできなかったのという記事を見かけましたので、実際にコードを書いてみましたので載せます。

参考

実行例

実行結果は以下になります。
WS000034.JPG

おそらく作者の方がやりたかったのはこのような感じかと思います。

コード

実際のコードですが、実装ですが2案用意してみました

案1

pythonファイルは以下になります。

buttonlauncher.py
# -*- coding: utf-8 -*
import kivy

from kivy.app import App
from kivy.config import Config
from kivy.uix.widget import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label

#from kivy.lang import Builder
#Builder.load_file('buttonlauncher.kv')

class MyWidget(GridLayout):
    def __init__(self):
        super(MyWidget, self).__init__()

class ButtonLauncherApp(App):
    def build(self):
        return MyWidget()


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

Kv Languageは以下になります。

buttonlauncher.kv
<MyWidget>:
    rows: 2
    cols: 2

    Button:
        text: 'button1'
    Button:
        text: 'button2'
    Button:
        text: 'button3'
    Button:
        text: 'button4'

案2

pythonファイルは以下になります。

buttonlauncher2.py
# -*- coding: utf-8 -*-

import kivy
kivy.require('1.9.0')

from kivy.app import App
from kivy.config import Config
from kivy.uix.widget import Widget
from kivy.uix.label import Label

from kivy.lang import Builder
Builder.load_file('buttonlauncher2.kv')

class MyWidget(Widget):
    def __init__(self ,**kwargs):
        super(MyWidget, self).__init__()

class ButtonLauncher2App(App):
    def build(self):
        return MyWidget()


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

Kv Languageは以下になります。

buttonlauncher2.kv
<MyWidget>
    GridLayout:
        rows: 2
        cols: 2
        size: root.size    # ★画面全体の値を取得する

        Button:
            text: 'button1'
        Button:
            text: 'button2'
        Button:
            text: 'button3'
        Button:
            text: 'button4'

解説

なぜ、 sizeに「root.size」をしないと 画面右下の一部しか表示されないかというとMyWidgetはWidgetを継承していますが、Widgetの初期値が100×100(ピクセル)だからです。KivyのUIはすべてWidgetクラスを基底クラスで持っているためサイズを何も指定せずに配置すると100×100となります。ちなみにこれは個人的にはそこそこ重要なことだと思いますが公式のチュートリアルには明記されておりません。
GridLayout自体はちょっと使用に癖があるのと、おそらくBoxLayout内で使用することを想定しているレイアウトのような気がしています。レイアウトに関してはBoxLayoutをまず使用してみて、そこからレイアウトの組み立てをしてみるといいと思います。

参考 設定画面

Kivyでは実行時にF1キーを押すと、コンフィグ画面が表示されます。これにより、Logレベルを変更したり、様々なことが可能です。

参考

参考 起動オプション

私も知りませんでしたが、Kivyでは起動時にパラメータを与えるだけで、widgetの階層構造をみたり、Propertyの値を確認できるモードがあります。参考のリンク先を一読することをお勧めします。

参考

Kivyを使用して作成に向いているアプリ

起動時の画面からボタンを押して、2~3画面に遷移するアプリなどは向いています。頻繁に画面を遷移してかつ、値を保持するようなアプリには向いていないのではと個人的には思っています。

また高精細な3Dモデルを表示するアプリも向いていないと思います。OpenGL ESを使用しているので3Dゲームなどに向いていると思っている方もいるかと思いますが、公式のAPIリファレンスでも言っていますが、インデックスが65535までしか表示できません。バリバリの3Dゲームを作成したい場合はUnityやUE4などのゲームエンジンを使用したほうがいいかと思います。

参考

この内容の続き

電卓アプリの作り方をあげました。
Python Kivyの使い方② ~電卓を作成する~

516
632
20

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
516
632