PySimpleGUI 入門 (3)
前回、YAML から画面を定義するライブラリ https://github.com/tmiya/tmiya.github.io/tree/main/python/sg_yaml を作って公開した、という話をしました。
実はちょっとだけ機能を追加して、Widget 全部に対して key=widgetのk
パラメータ、value=widget自身、という dictionary も YAML 解析時に生成する様にしました。これによってイベントループからwidgetの値の修正が楽になります。
という訳で今回は実際に動くアプリを作ってみます。
一目見て分かる人は何のためのツールなのか分かると思いますが(笑)、+
と -
のボタンを押すと能力値の値の Value
とそれに必要な割り振りポイントの Point
の数字が上下します。利用可能な割り振りポイントを過不足なく全部割り振ると能力値が決定出来るというものです。
コードは、https://github.com/tmiya/tmiya.github.io/blob/main/python/sg_yaml/attributes.py にあります。実行は $ python3 attributes.py
です。
YAML 自体には繰り返し機能などがないので、単に下記の様にフォーマット文字列を連結して YAML 文字列を生成しています。もしかしたら、Jinja のようなテンプレートエンジンを使った方が綺麗にかけるかもしれません。
for attr in attr_names:
s += f"""
- - Text:
_: {attr.capitalize()}
size: [4, 1]
font: ["Helvetica", 14]
- Text:
_: {str(attr_value[attr])}
size: [7, 1]
k: attr.{attr}.value
- Text:
_: {str(point_need[attr_value[attr]])}
size: [6, 1]
k: attr.{attr}.point
- Button:
_: "+"
size: [3, 1]
k: attr.{attr}.plus
disabled: false
- Button:
_: "-"
size: [3, 1]
k: attr.{attr}.minus
disabled: true
"""
ボタンなどのイベントハンドリングは
if event.startswith('attr.'):
es = event.split('.')
attr, sign = es[1], es[2]
match sign:
case "plus":
if attr_value[attr] < 15:
attr_value[attr] += 1
case "minus":
if attr_value[attr] > 8:
attr_value[attr] -= 1
case _:
print(f"unknown event: {event}")
for attr in attr_names:
rules.widgets[f"attr.{attr}.value"].update(value=str(attr_value[attr]))
rules.widgets[f"attr.{attr}.point"].update(value=str(point_need[attr_value[attr]]))
rules.widgets[f"attr.{attr}.plus"].update(disabled=(attr_value[attr] == 15))
rules.widgets[f"attr.{attr}.minus"].update(disabled=(attr_value[attr] == 8))
total = sum([point_need[attr_value[k]] for k in attr_names])
rules.widgets['attr.total.point'].update(value=f"{total}/{point_max}")
rules.widgets['attr.finish'].update(disabled=(not total == point_max))
こんな感じで、メインループのモデルオブジェクト attr_value
の値を増減しつつ、値に応じて表示の書き換えやボタンの disable
などの処理をしています。
モデルと表示内容の同期や、ボタンの disable 処理などは定型処理と思うので、こっちも YAML に書いて済ませたい気もします。そうすると、簡易インタプリタっぽいものを実装しないとダメかも。
という訳で、何か良い方法は無いか考えてみます。
Discussion