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

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

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

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

![result.jpg](https://qiita-image-store.s3.amazonaws.com/0/11002/430e7bfb-fbfd-94f3-a6a0-20da21ea91c5.jpeg)

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

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

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

 + [Kivy Language(APIリファレンス)](https://pyky.github.io/kivy-doc-ja/api-kivy.lang.html)


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

+ [Pycon JP 2017 の「kivyによるアプリケーション開発のすすめ」のソースコードの解説](https://qiita.com/dario_okazaki/items/b616e04da3541235fbd1)

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

+ [Technology Close to You様のKivy入門記事](https://www.closetoyou.jp/kivy/introduction-to-kivy01/)


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

+ [kivy戦記](https://koh-sen.jp/archives/6898)

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

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

+ [Github](https://github.com/okajun35/Kivy_practice/tree/master/example1)

## 検証環境

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

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

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


## エディターについて
Visual Studio code でKv言語に対応した拡張があります.

https://marketplace.visualstudio.com/items?itemName=BattleBas.kivy-vscode

## Python Kivyの使い方の一覧について
続き物として以下の投稿をしています。実際のアプリの作り方になります。

+ [Python Kivyの使い方②　～電卓を作成する～](http://qiita.com/dario_okazaki/items/910abf09344a60dd7823)
+ [Python Kivyの使い方③　～WebAPIとの連携（リクエストの送受信から結果表示まで）～](http://qiita.com/dario_okazaki/items/32446faff803a067d700)
+ [Python Kivyの使い方④　～Androidでの実行～](http://qiita.com/dario_okazaki/items/4f6373051afb70b794d9)

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

## １．空の画面を表示する

### 実行結果
![WS000000.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/5e4b89e7-6f2e-dc9c-5d12-968531d0972b.jpeg)

### コード

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

from kivy.app import App

App().run()

```
### Kvファイル
今回は使用しません

### 解説
Kivyの基本的な仕組みは [Programming Guide(翻訳済み) » Kivy Basics(翻訳済み)](https://pyky.github.io/kivy-doc-ja/guide/basic.html)を参考にしてください。

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


## 2．Appおよびラベルの表示

### 実行結果
![out.jpg](https://qiita-image-store.s3.amazonaws.com/0/11002/9c94a811-ccbb-4a22-33dc-3ca3e42a1cb8.jpeg)

### コード

```py3: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リファレンス（英語）を参考にしてください。

+ [App(API Reference)](https://kivy.org/docs/api-kivy.app.html)
+ [Label(API Reference)](https://kivy.org/docs/api-kivy.uix.label.html)


## 3．Appおよびラベルの表示（Kv Languageを用いたもの）

### 実行結果
![WS000002.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/26da984d-64aa-7d49-4ec2-129c2363f68b.jpeg)

### コード

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

class TestApp(App):
    pass

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

```
### Kvファイル

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

```

### 解説
２と違うのは、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内で

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

Kv Languageについては、ここでも解説しますが[Programming Guide(翻訳済み) » Kv language(翻訳済み)](https://pyky.github.io/kivy-doc-ja/guide/lang.html)を一読することをお勧めします。

参考

+ [Kivy Language(API Reference)](https://kivy.org/docs/api-kivy.lang.html) 

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

+ 参考　[PythonのGUIライブラリKivyによるクロスプラットフォームGUIアプリ作成入門
](http://myenigma.hatenablog.com/entry/2016/05/10/221433)

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

#### [Note] Kv Languageを書くファイルについて
Kv Languageですが、どのファイルに書くかですが3つのパターンが選べます。

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

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

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

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

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

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


参考

+ [Kvファイルのロード](http://code.tiblab.net/python/kivy/kv_load)

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

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

+ [Python Kivyの使い方（参考）～APIリファレンスのKivy Languageを翻訳してみた～ include](http://qiita.com/dario_okazaki/items/680b293be0fb2a5f9e60#include-)

#### [Note] Kv Languageのプレビューツールについて
2017/07/14t追加

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

参考

+ [kviewer 結果を確認しながらKvファイルが書けるツール](http://qiita.com/gotta_dive_into_python/items/c32cdcb58c66f0a1b840)




## 4．複数のラベルの表示

### 実行結果
![WS000004.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/e7bffcc3-a3e6-c902-da2c-4f008e5d80f8.jpeg)

### コード
（３．の内容と変更はありません。）

### Kvファイル

Kv Languageは以下になります。

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

```

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

公式マニュアルから転載
![boxlayout.gif](https://qiita-image-store.s3.amazonaws.com/0/11002/4a2561eb-99be-063b-82b9-94614b74b02d.gif)

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

参考

+ [Getting Started(翻訳済み) » Layouts(翻訳済み)](https://pyky.github.io/kivy-doc-ja/gettingstarted/layouts.html)
+ [Programming Guide(翻訳済み) » Widgets(翻訳済み)](https://pyky.github.io/kivy-doc-ja/guide/widgets.html#)
+ [Box Layout(API Reference)](https://kivy.org/docs/api-kivy.uix.boxlayout.html)

## ５．複数のラベルの表示（縦並びにする）

### 実行結果
![WS000005.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/c87d8d85-9c67-ca9d-7dac-ed384a8f13eb.jpeg)

## コード
（３．の内容と変更はありません。）

### Kvファイル

Kv Languageは以下になります。

```py3:test.kv
BoxLayout:
    orientation: 'vertical'     # 'horizontal'だと横一列
    
    Label:
        text: "Good Morning"
    Label:
        text: "Hello"
    Label:
        text: "Good Evening"

```


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


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


## 6．サイズの調整

### 実行結果
![WS000006.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/29f00076-93d0-c8af-da5a-588279f54679.jpeg)


### コード
（３．の内容と変更はありません。）

### Kvファイル

Kv Languageは以下になります。

```py3: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**に値を加えることでｙ方向の大きさが変わります。デフォルトでは両方とも１に設定されています。
大きさは画面全体の大きさ分の各比率になります。
例として今回の場合は"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～１が有効な範囲となっていますが、実際にコードを書くとわかるのですが、値を*10や100といれても有効に機能しています*ので、マニュアルかKivy内部の実装のどちらかがあっていないようです。

## 7．サイズの調整2

### 実行結果

![WS000007.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/bc91696c-55c7-fa4e-eb91-fcce42d76276.jpeg)

### コード
（３．の内容と変更はありません。）

### Kvファイル

Kv Languageは以下になります。

```py3: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の場合と値を変えてみました。


## ８．文字の色とラベルの色の変更


### 実行結果
![WS000008.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/2b93e526-7863-b73a-2c54-685bc3e2aa89.jpeg)

### コード

```py3: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ファイル

```py3: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クラスの初期化の際に以下のコマンドを入れています。

```py3
self.title = 'greeting'    # ウィンドウの名前を変更
```
こうすることで起動時のwindowの左上に表示されるタイトル名を変更することができます。

参考

+ [タイトル変更](http://code.tiblab.net/python/kivy/app_title)

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

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

①　canvasコマンドで色をつけます。beforeはここでは詳しく説明しません、canvasに関しては [Programming Guide(翻訳済み) » Graphics (翻訳済み)](https://pyky.github.io/kivy-doc-ja/guide/graphics.html)を読んでください。
②に関しては（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)の色の四角形を描画できます。図形は四角形の他にも三角形、円、線を描くことができます。

参考

+ [canvasの説明（API Reference）](https://kivy.org/docs/api-kivy.graphics.instructions.html)

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

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

※  [Kvファイルの予約語](http://code.tiblab.net/python/kivy/kv_reserved_keywords)から引用

参考

+ [Kvファイルの予約語](http://code.tiblab.net/python/kivy/kv_reserved_keywords)
+ [予約語の説明（API Reference）](https://kivy.org/docs/api-kivy.lang.html#value-expressions-on-property-expressions-ids-and-reserved-keywords)

## 9．ボタンの追加

### 実行結果
![WS000010.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/132b7f37-d4e5-2b7d-38eb-5071767ec2fd.jpeg)

### コード
~~（８．の内容と変更はありません。）~~
2018/02/03追加：ネット上でご指摘がありました。８．のままだとエラーになります。

```py3: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は以下になります。

```py3: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](https://qiita-image-store.s3.amazonaws.com/0/11002/8e1e5d7a-4228-0843-8098-23fe73f63d0e.jpeg)

### コード

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

```py3: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は以下になります。

```py3: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側のコマンドですが、

```py3
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(翻訳済み)](https://pyky.github.io/kivy-doc-ja/guide/events.html)を参考にしてください。
実際のコード上ではこの後、TextWidgetクラスでクラス変数textを宣言しておりそこでStringProperty() を代入しています。その後、「__init__」メソッドではtextには空白を代入しており、buttonClicked()関数を作成して、その中でtextに「Hello World」の文字を代入しています。

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

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

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

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

```py3

        # ラベル
        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」がありこちらはボタンが離された場合に実行されるイベントになります。

参考

+ [Button Behavior(API Reference)](https://kivy.org/docs/api-kivy.uix.behaviors.button.html#kivy.uix.behaviors.button.ButtonBehavior)



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

### 実行結果
起動時
![WS000013.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/60718bbf-2a09-f388-0b95-26e6bb922ebd.jpeg)

moriningをクリック
![WS000014.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/488f7c05-51e8-f3e8-2ca4-e90cf38025f3.jpeg)

dayをクリック
![WS000015.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/84e75a76-cb11-5697-5bda-be912fe0a304.jpeg)

nightをクリック
![WS000016.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/6979f389-8148-cbb1-4a7b-6e6c3ce77b77.jpeg)

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

```py3: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は以下になります。

```py3: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ですがボタンを押した際の動作は前回に説明をしたので問題ないかと思います。問題はレイアウトのほうで、今回は以下の構造をしています

```py3
<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つ追加されていますので、結果として横にボタンが３つ並べたレイアウトになります。
BoxLayoutを2つ組み合わせることにより、画面の上半分 は1つ、下半分は水平に3分割のレイアウトができます。
**Kivyでは複数のLayoutを組み合わせることで複雑なレイアウトを設置することが可能になります。**



## 12．レイアウトを変更

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

起動時
![WS000017.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/03a4e7f4-9ef6-1c8b-af40-4c7ba73ae6c6.jpeg)

moriningをクリック
![WS000018.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/54e248a6-66d2-5ca7-5820-3582dc38c747.jpeg)

dayをクリック
![WS000019.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/d24cfe92-60ac-67f5-eadb-73b32eb4470c.jpeg)

nightをクリック
![WS000020.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/59fed93f-e74b-747a-c600-7d4c554f1850.jpeg)


### コード
11と変化ありません。

### Kvファイル
Kv Languageは以下になります。

```py3: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を使用してサイズ調整をしています。上半分の、ラベルの縦のサイズが大きくなり、下半分のボタンのサイズが小さくなります。


## 1３．クリック時の機能追加(文字の色を変更する)

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

起動時
![WS000021.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/b9207405-440d-38fd-4b64-eb7daf603303.jpeg)

moriningをクリック
![WS000022.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/5dec1e6f-0be3-bc7a-bab2-040eda7a73f0.jpeg)

dayをクリック
![WS000023.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/32bd08db-4f06-daed-8086-0e462ad5b3d6.jpeg)

nightをクリック
![WS000024.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/5632a943-be45-d7ab-8bac-8e99785b7d61.jpeg)
### コード

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

```py3: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は以下になります。

```py3: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](https://qiita-image-store.s3.amazonaws.com/0/11002/fb2cee14-87ac-66bf-0017-54dcceab3b23.jpeg)

朝をクリック
![WS000026.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/4dd25b35-804d-cb42-ac7c-65717f1f1354.jpeg)

昼をクリック
![WS000027.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/f5dfcacc-c28e-9f9d-3be2-f6334099637e.jpeg)

夜をクリック
![WS000028.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/0f6c594b-66ce-1861-9f2d-3ff4630516db.jpeg)

### コード

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

```py3: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は以下になります。

```py3: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コード側で

```py3
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](https://kivy.org/docs/api-kivy.utils.html)という機能があり、これを使用すると実行時のOSを取得できます。これを用いてOSごとにデフォルトで表示するフォントを変更することができます。日本でも実際にやられている方がいます。

参考

+ [Tofu issue 日本語フォントの表示 - Kivy Advent Calendar 2013](http://d.hatena.ne.jp/cheeseshop/20131202/1385936070)

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

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

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

[Python: インポートするだけで Kivy が日本語を表示できるようになる japanize-kivy を作った](https://blog.amedama.jp/entry/japanize-kivy)

参考

+ [Kivyアプリに日本語を表示させる](http://supportdoc.net/support-kivy/03jp.html)
+ [kivyで日本語表示](http://yukirinmk2.hatenablog.com/entry/2014/06/02/220608)
+ [Kvファイルで日本語を使う](http://code.tiblab.net/python/kivy/kv_japanese)
+ [Kivy recipe: connecting font file](http://cheparev.com/kivy-connecting-font/)



#### 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](https://qiita-image-store.s3.amazonaws.com/0/11002/7d7ef21f-79f7-d142-b99a-b6e5a6d12212.jpeg)


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

```py3: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は以下になります。

```py3: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()
                
```
### 解説
画像だとわかりにくいですが、起動すると画面サイズが小さくなっているのがわかります。

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

Pythonファイルがわの冒頭で以下のコマンドが追加されています。
Kivyはインストール直後のデフォルトの設定では、解像度が800×600で起動するようになっています。[Programming Guide(翻訳済み) » Configure Kivy(翻訳済み)](https://pyky.github.io/kivy-doc-ja/guide/config.html)に書いてありますが、Kivyには「config.ini」というファイルで基本的な設定はそこに記載されています。
 Windowsでは*C:\Users\<ユーザ名\.kivy *配下にあります。「config.ini」の中身は以下のようになっています。
 
 ```py3
[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で簡単なアプリを作ってみる](http://tkitao.hatenablog.com/entry/2014/10/10/083252)

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

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


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

 ```py3
<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(翻訳済み)](https://pyky.github.io/kivy-doc-ja/guide/lang.html)を読んでみてください。

 
 
## 16．画像の表示

### 実行結果

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

起動時
![WS000033.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/8d42350d-1a40-8d63-184c-cab51395f759.jpeg)

### コード

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

```py3: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は以下になります。

```py3: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では画像を表示することが可能です。

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

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

参考

+ [Image(API Reference)](https://kivy.org/docs/api-kivy.uix.image.html)


## 17．画像の表示（ボタンによる画像切り替え）

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

起動時 or サンプル１をクリック時
![WS000000.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/98a4f3e5-34a6-0f8e-f41d-08ab84e7712b.jpeg)

サンプル２をクリック時
![WS000001.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/366575e8-1909-6a49-9086-331e83afd5ca.jpeg)

サンプル３をクリック時
![WS000002.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/6bf92a13-3108-ea92-e69b-61414e7e4c4e.jpeg)

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

```py3: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は以下になります。

```py3: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()](https://kivy.org/docs/api-kivy.graphics.texture.html#kivy.graphics.texture.Texture.blit_buffer)を使用することで実現できます

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

[Python KivyでOpencvやPillowで画像を表示する方法](https://qiita.com/dario_okazaki/items/fc8ae0525f2e8036cde7)

参考

+ [[Python] QRコード作成 - Kivy Advent Calendar 2013](http://d.hatena.ne.jp/cheeseshop/20131203)

# まとめ
 ここまでのことで、レイアウトの基本的な説明とボタンをクリックした際の動作の実行を説明しましたので簡単なアプリの実装はできるようになったかと思います。
 ここまでの内容を読んで、[公式マニュアルの翻訳サイト](https://pyky.github.io/kivy-doc-ja/)の「Programming Guide」を読み直すと色々な発見があると思いますので、一度通して読み直すことをお勧めします。
 
 またKivyのサンプルプログラムですが、Kivyの[example配下](https://github.com/kivy/kivy/tree/master/examples)には様々なサンプルがあるのでぜひ一度見てみるとよいと思います。
 どういったプログラムがあるかは、[Gallery of Examples(翻訳済み) » Gallery(翻訳済み)](https://pyky.github.io/kivy-doc-ja/examples/gallery.html)と[Getting Started(翻訳済み) » Examples(翻訳済み)](https://pyky.github.io/kivy-doc-ja/gettingstarted/examples.html)に内容の説明があります。
 
 Kivy自体は機能がたくさんありますがこれを読んで何か参考になれば幸いです。
 また有志による[公式マニュアルの翻訳](https://github.com/pyKy/kivy-doc-ja)もやっておりますので興味があれば参加してみてください。2017年はAPIを中心にやっていいこうと考えています。
 
## 参考　ファイルを選択する
Kivyでファイルを選択する際は[FileChooser](https://kivy.org/docs/api-kivy.uix.filechooser.html)を使用してファイル選択ダイアログを開くことができます

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

参考

+ [Kivyで、シンプルなミュージックプレイヤー①](https://torina.top/main/302/)



## 参考　日本語の入力について（注意）
以下はテキストボックスに文字を入れて「OK」ボタンをクリックするとラベルに入力された文字が表示されます。

### 実行結果
実行結果は以下の通りです。
![result.jpg](https://qiita-image-store.s3.amazonaws.com/0/11002/9546be03-d00a-917b-4d7d-2df6cf1fa0e9.jpeg)

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

```py3: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は以下になります。

```py3: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](https://kivy.org/docs/api-kivy.uix.textinput.html) を使用すると、テキストを入力できます。

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

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

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

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

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

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

+ [Kivyの日本語入力の文字を表示するようにした話](http://qiita.com/dario_okazaki/items/8c6953166b336e83e417)

+ [Kivyで日本語入力を行う方法について（実行編）]
(https://qiita.com/dario_okazaki/items/815cdebe91211f2b3826)


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

- [Kivyで日本語入力](https://qiita.com/nawonaototomousu/items/0a2a5e22aeb82535532a)

- github: https://github.com/Naotonosato/MilletPie
    - DLLはここにあります。

- 作った人：https://weekly.ascii.jp/elem/000/000/436/436756/

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

## 参考　kvファイルの値をPython側で取得する方法
「日本語の入力について（注意）」についてのコードを見るとTextInputは以下のコードになっています。

```py3:test.kv

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

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

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

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


### 実行例
実行結果は以下になります。
![WS000012.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/8e1e5d7a-4228-0843-8098-23fe73f63d0e.jpeg)

### コード

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

```py3: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は以下になります。

```py3: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の関数を呼び出します。

```

### 解説

```py3: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しています。詳しい使用方法は以下になります

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

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

参考

+ [Kivy Language -> Directives(API Reference)](https://kivy.org/docs/api-kivy.lang.html#lang-directives)

## 参考　GridLayoutの使いかた

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


参考

+ [Python の GUI フレームワーク kivy を使ったけどムズすぎて断念した in Windows7 and Python2.7](http://d.hatena.ne.jp/shouh/20161015/1476489961)

### 実行例
実行結果は以下になります。
![WS000034.JPG](https://qiita-image-store.s3.amazonaws.com/0/11002/2057952b-328b-d0e9-1357-185bad14e4d9.jpeg)

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

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

####案１

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

```py3: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は以下になります。

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

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

```

####案２

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

```py3: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は以下になります。


```py3: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の設定画面について](http://qiita.com/Ds110/items/457db343467178957264)
+ [Application（API Reference）](https://kivy.org/docs/api-kivy.app.html)

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

 参考

+ [Kivyアプリ実行時に引数を与えるだけで使えるようになる便利なツール群](http://qiita.com/gotta_dive_into_python/items/caa3e0f41ddfaedcdb95) 
+ [Modules（API Reference）](https://kivy.org/docs/api-kivy.modules.html)
  
# Kivyを使用して作成に向いているアプリ
起動時の画面からボタンを押して、2～3画面に遷移するアプリなどは向いています。頻繁に画面を遷移してかつ、値を保持するようなアプリには向いていないのではと個人的には思っています。
 
また高精細な3Dモデルを表示するアプリも向いていないと思います。OpenGL ESを使用しているので3Dゲームなどに向いていると思っている方もいるかと思いますが、公式のAPIリファレンスでも言っていますが、インデックスが65535までしか表示できません。バリバリの3Dゲームを作成したい場合はUnityやUE4などのゲームエンジンを使用したほうがいいかと思います。



参考

+ [class kivy.graphics.Mesh](https://kivy.org/docs/api-kivy.graphics.html#kivy.graphics.Mesh)

# この内容の続き

電卓アプリの作り方をあげました。
[Python Kivyの使い方②　～電卓を作成する～](http://qiita.com/dario_okazaki/items/910abf09344a60dd7823)