QPython には QSL4A が搭載されている
QPython には GUI で動く環境がいくつか用意されており、 SL4A をQPython用に改造した QSL4A (プロジェクト化したものが QSL4AApp)なるものがその一つ。
以下の記事だと QuietScripts と表記されているものがそれに該当すると思われるが、初期生成されるサンプルスクリプトは異なる。
この QSL4A や QSL4AApp、検索してもほとんど情報が出てこない。
SL4A などのページも参考に、 QPython での GUI プログラミングを試してみたい。
サンプルスクリプト
Editor で新規作成ボタン(+
)を押すと、 File(コンソール用)の他に、 ConsoleApp、WebApp、QSL4AApp、PygameApp を選ぶことができる。
QSL4AApp を選びプロジェクト名を付けると、 project3 フォルダの中にプロジェクト名のフォルダが生成され、サンプルスクリプトとなる main.py が開く。
このサンプルスクリプトを実行すると、 Hello, QPython
のメッセージと、下部に LOAD
・ EXIT
の2つのボタンが出てくる。
EXIT
ボタンを押すと終了してエディタ画面に戻る。
サンプルスクリプトを各部に分けて見てみる
1. 前処理部
#qpy:quiet
#-*-coding:utf8;-*-
"""
This is a sample project which use SL4A UI Framework,
There is another Sample project: https://github.com/qpython-android/qpy-calcount
"""
import qpy
import androidhelper
try:
import urllib.request as ur
except:
import urllib as ur
from qsl4ahelper.fullscreenwrapper2 import *
droid = androidhelper.Android()
冒頭でコンソールを出さない設定 #qpy:quiet
、モジュールのインポート等が行われている。
2. XML で画面レイアウト
class MainScreen(Layout):
def __init__(self):
super(MainScreen,self).__init__(str("""<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ff0E4200"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="@+id/logo"
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="10"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0px"
android:orientation="horizontal"
android:layout_weight="20">
<TextView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textSize="8dp"
android:text="Hello, QPython"
android:textColor="#ffffffff"
android:layout_weight="1"
android:gravity="center"
/>
</LinearLayout>
<ListView
android:id="@+id/data_list"
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="55"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0px"
android:orientation="horizontal"
android:layout_weight="8">
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Load"
android:id="@+id/but_load"
android:textSize="8dp"
android:background="#ffEFC802"
android:textColor="#ffffffff"
android:layout_weight="1"
android:gravity="center"/>
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="Exit"
android:id="@+id/but_exit"
android:textSize="8dp"
android:background="#ff06AF00"
android:textColor="#ffffffff"
android:layout_weight="1"
android:gravity="center"/>
</LinearLayout>
</LinearLayout>
"""),"SL4AApp")
どうやら @+id/
のついた部分は下記の関数等で差し替えたり機能を持たせたりできるようだ。
3. 関数定義
def on_show(self):
self.views.but_exit.add_event(click_EventHandler(self.views.but_exit, self.exit))
self.views.but_load.add_event(click_EventHandler(self.views.but_load, self.load))
pass
def on_close(self):
pass
def load(self, view, dummy):
droid = FullScreenWrapper2App.get_android_instance()
droid.makeToast("Load")
saved_logo = qpy.tmp+"/qpy.logo"
ur.urlretrieve("https://www.qpython.org/static/img_logo.png", saved_logo)
self.views.logo.src = "file://"+saved_logo
def exit(self, view, dummy):
droid = FullScreenWrapper2App.get_android_instance()
droid.makeToast("Exit")
FullScreenWrapper2App.close_layout()
イベントの定義と、イベント発生時に行う機能の定義。
4. メイン
if __name__ == '__main__':
FullScreenWrapper2App.initialize(droid)
FullScreenWrapper2App.show_layout(MainScreen())
FullScreenWrapper2App.eventloop()
初期化して、XML をもとにレイアウトして、イベント発生を待つ…ということのようだ。
Load ボタンを押すと真ん中の文字が表示されるようにしよう
このサンプルスクリプトでトースト通知と画像の表示の方法はわかったが、文字の差し替え・表示についてはわからない。
サンプルスクリプトが紹介している qpy-calcount のソースを見てみると、どうやら
self.views.((ID名)).text = "((表示させたい文字))"
とすればよいようだ。
XML 部分、 Load 部分を以下のように修正してみる(一部抜粋、このほか datetime
モジュールの呼び出しや文字サイズの適宜修正をした)。
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0px"
android:orientation="horizontal"
android:layout_weight="10">
<TextView
android:id="@+id/time"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textSize="20dp"
android:text=""
android:textColor="#ffffffff"
android:layout_weight="1"
android:gravity="right"
/>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0px"
android:orientation="horizontal"
android:layout_weight="20">
<TextView
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textSize="30dp"
android:text=""
android:textColor="#ffffffff"
android:layout_weight="1"
android:gravity="center"
/>
</LinearLayout>
def load(self, view, dummy):
curdatetime = datetime.datetime.now()
self.views.time.text = curdatetime.time().isoformat()[0:8]
self.views.title.text = "Load button pressed!"
うまくいった。今回はここまで。
次回はこのスクリプトを発展させ YouTube チャンネル登録者数カウンターにする予定。