Kivyで簡単なアプリを作ってみる
ここのところKivyのサンプルを動かしたりソースコードを読んだりしているのですが、 仕様がムダなく洗練されていていい感じですね。モバイル環境ではまだ試せていないのですが、Kivyがいろんな用途で今後もっと広まっていくといいなと思います。
今日はこれまで勉強したことの復習も兼ねて、シンプルなアプリを作ってみたいと思います。
今回作るアプリ
電卓でも作ろうかと思ったのですが、ボタンの数が多くて面倒そうだったので、今回は下のイメージのようなシンプルなタイマーアプリを作ることにします。
+1 minute
ボタンで残り時間を60秒追加、Start/Stop
ボタンでカウントダウンの開始と停止。Reset
ボタンで残り時間を0に戻す単純な仕様です。
アプリのコード
アプリのコード全文は以下のとおりです。
from kivy.config import Config Config.set('graphics', 'width', '300') Config.set('graphics', 'height', '150') from kivy.lang import Builder from kivy.uix.widget import Widget from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.uix.button import Button from kivy.properties import BooleanProperty from kivy.properties import NumericProperty from kivy.clock import Clock from kivy.app import App Builder.load_string(''' #:kivy 1.8.0 <KivyTimer>: BoxLayout: orientation: 'vertical' pos: root.pos size: root.size Label: text: str(root.left_time) font_size: 100 BoxLayout: orientation: 'horizontal' size_hint: 1.0, 0.3 Button: text: '+1 minute' font_size: 16 on_press: root.on_command('+1 minute') Button: text: 'Stop' if root.is_countdown else 'Start' font_size: 16 on_press: root.on_command('start/stop') Button: text: 'Reset' font_size: 16 on_press: root.on_command('reset') ''') class KivyTimer(Widget): is_countdown = BooleanProperty(False) left_time = NumericProperty(0) def on_command(self, command): if command == '+1 minute': self.left_time += 60 elif command == 'start/stop': if self.is_countdown: self.stop_timer() elif self.left_time > 0: self.start_timer() elif command == 'reset': self.stop_timer() self.left_time = 0 def on_countdown(self, dt): self.left_time -= 1 if self.left_time == 0: self.is_countdown = False return False def start_timer(self): self.is_countdown = True Clock.schedule_interval(self.on_countdown, 1.0) pass def stop_timer(self): self.is_countdown = False Clock.unschedule(self.on_countdown) pass class KivyTimerApp(App): def build(self): return KivyTimer() if __name__ == '__main__': KivyTimerApp().run()
ポイントを順に解説します。
ウィンドウサイズの設定
Kivyでは専用の設定ファイル(.iniファイル)でウィンドウサイズの設定を行いますが、今回はファイルを一つにまとめるために、Cofigクラスを使用して直接パラメータを設定しています。
Config.set('graphics', 'width', '300') Config.set('graphics', 'height', '150')
Configの値が他のモジュールに影響を与える場合があるため、設定は他のモジュールをインポートする前に行います。
ウィジェットの配置
ウィジェット(UI部品)の配置は専用のKV言語を使用して行います。こちらも別ファイルに分けることができるのですが、今回はBuilderクラスを使用してコード内に直接KV言語を記述しています。
Builder.load_string(''' #:kivy 1.8.0 ここにKV言語を記述 ''')
KV言語内ではアプリケーションとデータのやり取りを行うために、ウィジェットのパラメータとしてルートウィジェット(KivyTimerクラス)のプロパティやメソッドをroot.
で指定しています。
# ラベルに残り時間を表示する Label: text: str(root.left_time)
# ボタン押下時にルートウィジェットのon_commandメソッドを呼ぶ Button: on_press: root.on_command('+1 minute')
# ルートウィジェットのis_counddownプロパティに応じてボタンの表記を変更する Button: text: 'Stop' if root.is_countdown else 'Start'
アプリケーションコードの記述
アプリケーションの動作内容は、ルートウィジェットとして使用するKivyTimerクラス内で記述します。
クラスの先頭でKV言語で引用しているプロパティを定義します。
class KivyTimer(Widget): is_countdown = BooleanProperty(False) left_time = NumericProperty(0)
ボタンが押された際に呼ばれるコールバック用のメソッドも定義します。ここでは引数としてボタンの種類を表す文字列を受け取り、値に応じて処理を分岐させています。
def on_command(self, command): if command == '+1 minute': self.left_time += 60
終わりに
Kivyで簡単なアプリを作ってみました。いつものProcessingのサンプルと比べると、クラス定義などのためコードのボリュームがそれなりにありますが、アプリに必要な要素を一通り押さえていると考えると、かなり簡潔な記述が出来ていると思います。
また、KV言語のおかげで直感的にウィジェットの設定ができる一方、プロパティの自動連動等、暗黙の仕様も多いので、そのあたりの理解がKivy習熟の早道のように感じました。