PythonでAndroidアプリ作成してみる #2 kivyのGUIテスト
前回はアプリと言えないレベルでの動作確認まで行いました。
今回は操作の要となるGUIの部分を確認していきます。
本シリーズはこちら
はじめに
調べるとkivyでのGUI作成にはいくつか方法があるようですが、今回はGUIだけ別の"kv"ファイルを作成していく分離方法を取ります。
理由としてはリアルタイムビューアーが使えるからです。
※少し進んだ後追記。クラスから操作できるような書き方をするとプレビューできなくなります。
また、書き方については公式を日本語訳した下記サイトを参考にしていきます。
後は情報が結構古いようなので、ChatGPTに質問しつつ進めていく感じです。
日本語化
初期状態では日本語が使えないみたいなので、日本語化ライブラリを導入します。
※後述しますがkvファイル内では日本語を使わないこと。
pip install japanize-kivy
import japanize_kivy
GUI構成について
kivyでは、レイアウトとウィジェットというものを使ってguiを作成していきます。
レイアウトとは画面の配置用制御するための枠組みのようなものです。グリッドであれば縦横綺麗に並べることができます。自由なレイアウトであればフロートというのもあります。
ウィジェットとはボタンやラベルなどの他言語で言う要素のことですね。
簡単に絵に書いてみるとこんな感じでしょうか?
画面の中に用意されたレイアウトを敷き詰めていき、一番内側にボタンやラベルなどのウィジェットを配置していくと言った感じです。
もちろんレイアウトの中にレイアウトを入れることもできるので、一番外側で大枠なレイアウトを作っておき、中で細かく調整またはその逆といったこともできます。
こちらに詳しく書いてあります。
アプリの作成
ファイル構成
今回はPythonファイルと別にguiは専用のファイルを用意します。
なので、ファイル構成としては以下のようになります。
Pythonの方で処理。本体やボタンが押された時のイベントなどを定義しておき、KVファイルの方でguiのレイアウトに関する記述を行っていきます。
とりあえずユーザー定義レイアウトをやってみる
とりあえずイベントの発生などをやってみたいため、下記のようなレイアウトで実施していきます。
レイアウト解説
中身は下記のようになっています。
※この内容は最終的にOKの内容。途中経過では若干違う内容だったりします。
kvファイル
まずはレイアウトの方から見ていきましょう。
前提として、MainLayerというカスタムレイアウトが最背面にあり、その上にBoxLayout_Layer1というカスタムレイアウトが乗っています。
カスタムレイアウトは<>で囲んだ任意の名前のレイアウトであり、クラスのように事前に定義して任意の箇所でインスタンスするようなイメージで使えます。
MainLayerはFloatLayoutを継承しているのでMainLayer内は自由にモノが置けます。
たとえば"Rcat999 App"ラベルは中央上から10%に配置されています。
その下にBoxLayout_Layer1が入っています。こちらは特に指定していないので全画面に広がって配置されるようです。
BoxLayout_Layer1の中身はラベルとボタンで、垂直表示なので上下2分割ですね。
ラベルの表示には"root.label_text"と入力してPython側で変更できるようにします。
似たように、ボタンはbuttonClicked()関数の呼び出しが紐づけられています。
これだけではよくわからないと思うので、Python側も同時に見ましょう。
<BoxLayout_Layer1>:
orientation: 'vertical'
Label:
text: root.label_text
id: label1
Button:
id: button1
text: "ボタンを押してね"
font_size: 24
on_press: root.buttonClicked()
<MainLayer>: #FloatLayout
Label:
text: "Rcat999 App"
font_size: 36
pos_hint:{'center_x': 0.5, 'center_y': 0.9}
size_hint:(None,None)
BoxLayout_Layer1:
MainLayer:
pyファイル
こちらがPython側になります。
前提として、カスタムレイアウトはクラスにするというルールがあります。
そして、そのクラスでkivyのレイアウトを継承することでレイアウトの種類が決定します。
下記を見ての通り、MainLayerはFloatLayoutでBoxLayout_Layer1はBoxLayoutを継承していますね。
特にアクションを起こさないMainLayerは空のクラスです。
ポイントはアクションを起こすレイアウトですね。
ラベル用に"root.label_text"というのがいましたが、クラス変数にlabel_textというのが宣言されておりこれに対応しています。
ボタンの"root.buttonClicked()"はbuttonClickedメゾットに結び付いています。つまりrootとはカスタムレイアウトのクラスの事ですね。
最後に、mainmenuAppのbuildメゾットで一番最下層のレイアウトを返せば完了です。
from kivy.app import App
from kivy.properties import StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
import japanize_kivy
class BoxLayout_Layer1(BoxLayout):
label_text = StringProperty()
def buttonClicked(self):
self.label_text = "ボタンを押しました"
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
class MainLayer(FloatLayout):
pass
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
class mainmenuApp(App):
def build(self):
self.title = 'RcatApp'
return MainLayer()
mainmenuApp().run()
解説していない部分は…まだ仕様確認段階です。
スマホにインストール
というわけでスマホに入れてどう表示されるのか確認します。
まずは即落ち
前回同様コンパイルして、いざインストール!!
・・・即落ちしました
→kvファイルの文字コードがSJISになっていました。
UTF-8(BOM無)に変更したら立ち上がりました。
次は画面真っ暗
気を取り直して日本語削除後起動
変ですね?画面が真っ暗です。
適当に情報をあさっていたところ、全く予想外の事態が判明…
"Linux環境ではファイル名は小文字でなければならない"
単語の先頭を毎回大文字にしてしまうのは私の癖です…。
やっと起動
というわけでkvファイル名とクラス名は完全に小文字に直して再コンパイル!
はい、起動しました。
まとめ
今回はスマホに任意のレイアウトのアプリをインストールまでやれました。
起動まで1日がかりでかかってしまいましたが、kvファイルの文字コードで落ちたり、大文字使うだけで画面真っ暗って…これは気づかない。
私のような思考をしている方がいればきっと参考になると思う。
次回は昨日の実装を進めていこうと思います。
kvファイルはUTF-8 (BOM無し)で記述する(SJISやBOM有は落ちる)
kvファイル名はすべて小文字にする。
以上
情報が役に立ったと思えば、僅かでも投げ銭していただけるとありがたいです。