kivyはデスクトップやモバイルをはじめとした様々なプラットフォームでGUIアプリを開発できるライブラリです。ここでは基礎となる.kvファイルの書き方をはじめ、簡単なウィジェットを作成してイベントを設定することでkivyに入門することを目標とします。
こんにちは。wat(@watlablog)です。ここではアプリ開発で注目されているkivyの簡単な使い方を学びます!
kivyを学ぶ前に知っておきたいこと
kivyとは?
kivyとは、PythonでGUIアプリケーションを開発するための外部ライブラリです。
WATLABブログではTkinterやwxPythonによってGUIアプリを作成する方法を紹介しましたが、kivyはそれらのライブラリとまた異なる特徴を持ちます。
ちなみにTkinterは「Python初心者がGUI作成にTkinterを選ぶ3つの理由」で紹介したように、Python標準で安定しており情報が多いことから初心者に優しいライブラリでした。
またwxPythonは「wxFormBuilderでwxPythonのGUIコード自動生成」に記載した通り、モダンなウィジェットが多いライブラリでした。さらに、wxFormBuilderというGUIコード自動生成ツールの存在が面倒なGUIプログラミングをサポートしてくれることも大きいと思います。
kivyはあまり日本語の書籍やブログが多くないので情報の収集という意味では上記ライブラリより上級者向けですが、さらに魅力的な以下の特徴を持つため是非習得したいライブラリです。
例によっていつでも1次情報は大切にしたいと思いますので、以下に公式ドキュメントのリンクと、有志による日本語翻訳ページのリンクをメモしておきます。筆者も基本的にはこのページを参照して学んでいます。
公式ドキュメント:https://kivy.org/doc/stable/
日本語翻訳ページ:https://pyky.github.io/kivy-doc-ja/
クロスプラットフォームに対応
モバイルやタッチパネルにも対応している
kivyの最大の魅力はなんといってもタッチパネル動作を含んだモバイルアプリに対応していることでしょう。
モバイルはiOSやAndroidに対応しており、これはiPhoneアプリやAndroidアプリといったスマホ向けアプリを開発できるということを意味します。
そしてモバイルに特化というわけでもなく、様々なデスクトップアプリにも対応しており、WindowsやmacOS、LinuxやRaspberry Piにも対応するといった充実ぶりです。
今のところkivyをマスターしておけば一般的なプラットフォームで困ることはないと言えるでしょう。
MITライセンス
kivyはバージョン1.7.2.以降はMITライセンスで配布されています。MITライセンスとは、著作権表示や許諾表示をすることで、ソフトウェアを誰でも無償で無制限に使用して良いという比較的緩いライセンスです。
MITライセンス(Wikipedia):https://ja.wikipedia.org/wiki/MIT_License
License¶
https://kivy.org/doc/stable/#license
Kivy is released and distributed under the terms of the MIT license starting version 1.7.2. Older versions are still under the LGPLv3.
You should have received a copy of the MIT license alongside your Kivy distribution. See the LICENSE file in the Kivy root folder. An online version of the license can be found at:
https://github.com/kivy/kivy/blob/master/LICENSE
kv言語でレイアウトを設定する
kivyのコーディング上の特徴として、kv言語を使うことが挙げられます。
TkinterやwxPythonはUI(ユーザーインターフェース)をPythonコード上で記述していました。
このブログでは「アプリ完成編:wxPythonで信号処理のGUIアプリをつくろう⑥」という記事で一つGUIアプリを作ってみました。記事内のコードをみるとわかりますが、Pythonコードの中にボタン等のUIを全て記述していて、やや難読性があります。
一方kivyは機能を記述する.pyファイルとは別に、ウィジェットのデザインをkv言語で構成される.kvファイルで記述します。
kv言語はWebページを作るHTMLファイルで使用されるCSSと似ています。本文と分けてレイアウトを設定することで、非常に可読性やメンテナンス性の良いGUIアプリを開発できます。
kivyの基本的な使い方
動作環境
このページのコードは以下の環境で動作確認をしています。
PC環境
Mac | OS | macOS Catalina 10.15.7 |
---|---|---|
CPU | 1.4[GHz] | |
メモリ | 8[GB] |
Python環境
Python | Python 3.9.6 |
---|---|
PyCharm (IDE) | PyCharm CE 2020.1 |
kivy | 2.1.0 |
インストール
インストール方法は以下の公式ページを参考にしましょう。公式は仮想環境で入れることを強く推奨しているそうです。
https://kivy.org/doc/stable/gettingstarted/installation.html
筆者はMac環境なので以下のコマンドでフルパッケージをインストールしてみました。
1 |
pip3 install "kivy[full]" kivy_examples |
Hello Worldコードで動作確認
まずは正常にインストールされたかどうかを確認するために、Hello Worldを表示させるだけのプログラムを書いてみましょう。
とりあえず新しい物事を始める時は必ずHello Worldしてみよう!
Hello World!プログラムはkvファイルを使わないで書きます。以下のコードを実行してみましょう。
1 2 3 4 5 6 7 8 9 10 11 |
from kivy.app import App from kivy.uix.label import Label class MyApp(App): title = 'My Application' def build(self): return Label(text='Hello World!') if __name__ == '__main__': MyApp().run() |
中心にHello World!と記載され、タイトルがMy ApplicationとなっているWindowが表示されたら成功です。
このようにkivyではAppという基本クラスをimportし、メイン文で.run()することでループが回ります。title等は属性の設定になるので、class文直下に記載します。
build()メソッドは初期化時に1回だけ実行されます。ここで様々なウィジェットを初期配置させる等を行います。
アイコンを設定する
class直下にアイコン画像をiconに設定することで、プログラム実行中にタスクバーに表示される画像を指定できます。
画像は背景透過処理を施したpngファイルをオススメします。任意色の透過処理をPythonで行う方法は「Python/OpenCVで任意色を透過させたpng画像に変換」をご覧ください。
いらないと思いますが、当ブログのアイコン画像をダウンロード可能としますので、お試しにどうぞ。
基本的なレイアウトとウィジェットの配置方法
kvファイルを使わない基本的なレイアウト設定について説明します。kivyでもTkinterやwxPythonと同様にウィジェットをクラスの設計図に基づいてインスタンス化(実体化)する工程が必要です。
また、ウィジェットの並び方はレイアウトメソッドで制御します。下のコードはBoxLayout()を使って縦方向にボタンを2つ配置するようにbuild()内に記述しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button class MyApp(App): title = 'My Application' def build(self): ''' ビルド時に1回だけ実行される ''' # レイアウトやウィジェットのインスタンス化 layout = BoxLayout(orientation='vertical') button1 = Button(text='Button1') button2 = Button(text='Button2') # レイアウトにウィジェットを追加 layout.add_widget(button1) layout.add_widget(button2) return layout if __name__ == '__main__': MyApp().run() |
動作はこんな感じです。
この構成は下図のようにツリー構造(青がレイアウト、緑が個々のウィジェットパーツ)として捉えるとより複雑な構成も理解しやすいです。
ウィジェットツリーの考え方でレイアウトする方法
ウィジェットをツリーとして考えるウィジェットツリーの考え方を使うことで、様々なウィジェットを入れ子構造にしてレイアウト可能です。
例えば、先ほどはBoxLayout()に2つのボタンを配置していましたが、上にさらにBoxLayout()とボタンを追加してみましょう。ツリー構造は下図です。
この時一番上にあるレイアウトメソッドをルート(根)と表現し、build()の戻り値にはこのルートを指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button class MyApp(App): title = 'My Application' def build(self): ''' ビルド時に1回だけ実行される ''' # レイアウトやウィジェットのインスタンス化 layout_root = BoxLayout(orientation='vertical') layout1 = BoxLayout(orientation='horizontal') button1 = Button(text='Button1') button2 = Button(text='Button2') button3 = Button(text='Button3') # レイアウトにウィジェットを追加 layout1.add_widget(button1) layout1.add_widget(button2) layout_root.add_widget(button3) layout_root.add_widget(layout1) return layout_root if __name__ == '__main__': MyApp().run() |
上記コードを実行すると、縦方向と横方向のBoxLayout()を組み合わせたボタン配置ができあがります。
レイアウトメソッドにはBoxLayout()の他、GridLayout()やStackLayout()、スワイプで切り替えることができるPageLayout()といった様々な種類があります。是非公式ページで「layout」と検索してみてください。
スワイプ処理を実装してみる
これだけは感動したのでコードをメモしておきます。以下のようにPageLayout()を使えばモバイルで多用するスワイプ処理が簡単に書けてしまいます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.pagelayout import PageLayout from kivy.uix.button import Button class MyApp(App): title = 'My Application' def build(self): ''' ビルド時に1回だけ実行される ''' # レイアウトやウィジェットのインスタンス化 layout_root = PageLayout() layout1 = BoxLayout(orientation='horizontal') button1 = Button(text='Button1') button2 = Button(text='Button2') button3 = Button(text='Button3') # レイアウトにウィジェットを追加 layout1.add_widget(button2) layout1.add_widget(button3) layout_root.add_widget(button1) layout_root.add_widget(layout1) return layout_root if __name__ == '__main__': MyApp().run() |
モバイルアプリで良く見る動作…こんなに簡単に書けるとは!
イベントの書き方
起動時
メインクラスにon_start()メソッドを追加することで、起動時のイベントを設定できます。
今回はprint文を書いたので、コンソールに文章が出るのみですが、ここにアプリ起動時のアニメーション等を書くとプロっぽいかも。
1 2 3 4 5 6 |
def on_start(self): ''' 初期化時のイベント ''' print('Initialization') return |
終了時
アプリを閉じるといった終了動作を行う場合はon_stop()メソッドに処理を記載します。
1 2 3 4 5 6 |
def on_stop(self): ''' 終了時のイベント ''' print('End of application') return |
一時停止時(モバイル)
iOSやAndroidのモバイル端末でアプリを実行している場合、アプリ実行中でもホーム画面に戻ったり異なる操作を行う場合が想定されます。
そのような一時停止が要求される場合はon_pose()メソッドを追記しておかないと(さらに戻り値をTrueにする)、再開時にアプリが終了してしまいます。
1 2 3 4 5 6 |
def on_pause(self): ''' ポーズ時のイベント ''' print('Pause') return True |
復帰時(モバイル)
一時停止(Pause mode)から復帰する時はon_resume()メソッドによる処理が実行されます。
1 2 3 4 5 6 |
def on_resume(self): ''' 復帰時のイベント ''' print('Return application') return |
ウィジェットの操作に対するイベント
各ウィジェットはそれぞれ固有の操作に対するイベントを設定可能です。kivyではkv言語を使ってイベントの設定を行い、詳細な動作はPythonスクリプトで書くというスタイルをとった方が可読性向上に繋がります。
kv言語については後述しますが、各ウィジェットがどのような動作に対するイベントを設定できるかは、公式ページからAPIを確認するのが良いでしょう。
例えばボタンの場合はクリックに対する動作が設定できますが、押した時on_press()と離した時on_release()があります。
kv言語によるアプリ開発方法
それではいよいよkivyプログラミングの真骨頂であるkv言語を使ったコーディングを見てみましょう。この章を一通り見ることで、基本的なレイアウト設定やイベント設定の方法習得を目指します。
kvファイルの作成と読み込み
kvファイルの命名規則
スタイルシートのような使い方ができるkvファイルは命名規則を守ることで特にファイル指定をする必要なく読み込むことができます。
アプリの基本クラス名が「MyApp」の場合は、Appより前の文字列を小文字にした「my」をファイル名にします。つまり拡張子をkvにした「my.kv」というテキストファイルを作成しておくことで自動的にファイルを読み込んでくれます。
ファイル名を指定して読み込む場合
以下のBuilderをimportしてload_fileを使ったコードで任意ファイル名のkvファイルを読み込むことも可能です。ファイル名を任意で付けたい場合や、テストでファイルを分けたい時にはこの方法で読み込みましょう。
1 2 3 |
from kivy.lang import Builder Builder.load_file('style.kv') |
kv言語でウィジェットを配置する
ここではkv言語とPythonファイルを2つ使って、ボタンを2つBoxLayoutで配置するコードを書いてみます。ウィジェットツリー図はこちら。
まずはkvファイル「my.kv」を以下に示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#:kivy 2.1.0 Root: <Root> BoxLayout: orientation:'vertical' Button: id:button1 text:'Button1' Button: id:button2 text:'Button2' |
Rootというクラスを定義(.pyファイルでも書く)して、「<>」で宣言をした後にウィジェットの配置を記述します。
Pythonと同様にインデントで入れ子構造を表現する仕様です。インデントにスペースとTabが混ざっている場合はエラーになるので注意しましょう。筆者は統合開発環境であるPyCharm上でファイルを作成してコーディングしています。
ボタン等の各ウィジェットパーツには固有のidを付与しています。これは後ほどイベントの動作を設定したり、コード上で各ウィジェットを呼びだすために使います。
次にPythonファイルである「main.py」を以下に示します。
1 2 3 4 5 6 7 8 9 10 11 12 |
from kivy.app import App from kivy.uix.boxlayout import BoxLayout class Root(BoxLayout): pass class MyApp(App): title = 'My Application' if __name__ == '__main__': MyApp().run() |
Pythonファイル内ではウィジェットのインスタンス化もadd.widget()もしないため非常にシンプルになりました。
実行結果は先ほどと同様ですが、一応動画を置いておきます。
kvファイルのみの修正でウィジェットを追加する
ここでラベルを追加してみましょう。ウィジェットツリー図はこちら。
ラベルの追加はkvファイルの修正のみで行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#:kivy 2.1.0 Root: <Root> BoxLayout: orientation:'vertical' Button: id:button1 text:'Button1' Button: id:button2 text:'Button2' Label: id:label1 value:0 text:str(self.value) |
Pythonファイルの修正なしにラベルを追加することができました。
kvファイルでイベント処理を行う
それではここでkvファイルを使ったイベント設定を学びます。
先ほど作成したボタンとラベルのレイアウトに対して、Button1を押したらLabelの数値が+1され、Button2を押したら0にリセットされるという動作を実装してみましょう。
kvファイルを以下に示します。Button1とButton2に対してon_releaseというイベント(クリックして離した時にイベントのトリガーがかかる)を設定しています。ボタンのテキストも少し変更してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#:kivy 2.1.0 Root: <Root> BoxLayout: orientation:'vertical' Button: id:button1 text:'+1' on_release:label1.value += 1 Button: id:button2 text:'Reset' on_release:label1.value = 0 Label: id:label1 value:0 text:str(self.value) |
こちらが結果です。今回もPythonファイルは編集していませんが、だんだんとアプリっぽくなってきましたね。
Pythonファイルでイベント処理を行う
kvファイル
kvファイルには先ほどと同じく、on_releaseの項目を追加します。ここに処理を書かず、「root.メソッド名」と指定することで、Pythonファイル側で記述したメソッドを実行できます。
今回はcount_up()とcount_reset()というメソッドを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#:kivy 2.1.0 Root: <Root> BoxLayout: orientation:'vertical' Button: id:button1 text:'+1' on_release:root.count_up() Button: id:button2 text:'Reset' on_release:root.count_reset() Label: id:label1 value:0 text:str(self.value) |
Pythonファイル
Pythonファイルは先ほどpassと書いていたところにメソッドを追加します。
処理内容は全く一緒ですが、今回はPythonファイル側で動作を記述し、kvファイル側ではあくまでイベント処理のトリガー検出をしているという内容です。複雑な処理を行う場合はこちらの方が良いでしょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from kivy.app import App from kivy.uix.boxlayout import BoxLayout class Root(BoxLayout): def count_up(self): self.ids.label1.value += 1 def count_reset(self): self.ids.label1.value = 0 class MyApp(App): title = 'My Application' if __name__ == '__main__': MyApp().run() |
まとめ
文量も多くなってきたため今回はここまでです。このページではkivyというGUIアプリ開発用外部ライブラリの基礎的内容をまとめてみました。
日本語の情報が比較的少ないと言われており今まで敬遠していましたが、公式ドキュメントを読み、怪しいところは日本語翻訳ページを確認しつつなんとか進めることができました。
今回はkivyのインストールからPythonコード、kvコードの書き方を紹介し、イベント処理までを習得しました。
今後はより実用的な処理の実装方法と、最終的には筆者も使っているiPhone用のアプリ作成まで到達することを目標とします。
kivyの利点はなんといってもモバイルやタッチデバイスへの対応ができる点です。世界中でスマホやタブレット端末の普及率が高まってきた現代において、簡単にそれら最新デバイス用のアプリが開発できるのは魅力的です。
また、Pythonは比較的習得が簡単なプログラミング言語です。iOSアプリを作るために新しくSwift等を覚えなくても良く、Pythonが持つ豊富な外部ライブラリを活用できる点もkivyの魅力の一つです。
このブログではちょっと前にPythonにHello Worldした筆者自身が学びながらコーディング例を紹介していく予定ですので、特に初心者Pythonistaの参考になると思っています。
kivyが思ったより簡単でハマりそうです!まさかスワイプ処理の実装がPythonでできるとは…!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!