非同期処理と GUI (P)
こちら にしたがって、TkEasyGUI を用いて GUI プログラムを書いている場合についてです。
定期的な処理
アニメーションなど、定期的に実行したい処理がある場合、window.read()
に `timeout`` option をつければ大丈夫です。
これで、GUI イベントが来なくても、指定時間が来たらイベントとして認識してくれます。
後は、定期的に実行したい処理を、対応 event として記述するだけ。
while True:
# 定期的に処理したいことがある場合は、timeout を指定するので十分
event, values = self.window.read(timeout=1000, timeout_key='timeout')
if event == sg.WIN_CLOSED:
break
print(f"event='{event}', code={ord(event[0])}, values={values}\n")
if event == 'timeout':
self.my_time.update(str(datetime.datetime.now()))
asyncio とGUI の協調
-
このプログラムは、webserver_test/test_server2.pyで起動される(偽)Web API にアクセスするプログラムとなっています。先に、
test_server2.py
を実行した状態で、simpleA_coroutine.py
を実行させてください。 -
GUI のハンドラの中では、await は実行せず、web API 呼び出しも
create_task
してadd_done_callback
を指定するだけにする。- これで、ハンドラの中で長時間停止することはない
- 以下はclick のハンドラの例
def listbox_click(self, value): # 学生クリック時の動作
if len(value) == 0: # value はクリック要素が list として渡される
return
task0 = asyncio.create_task(self.score_service.get_scores(value[0]))
task0.add_done_callback(callback_scores)
print('Click performed.', value)
- 一方で、定期的に co-routine にスケジュールの機会を与えないといけないので、Eventチェックの前に asyncio 処理を入れる
while True:
await asyncio.sleep(0.01) # 他の co-routines にスケジュール機会を与えるため
# GUI Event は、timeout を設定。しないと、GUI event 来るまで「止まり」、
# co-routine を見てくれなくなる
event, values = self.window.read(timeout=200, timeout_key='timeout')
if event == eg.WIN_CLOSED:
break
if event == 'timeout':
continue
print(f"event='{event}', code={ord(event[0])}, values={values}\n")
if event == 'listbox':
self.listbox_click(values['listbox'])
練習問題
課題作成に向けて、色々考えてみましょう。
- まえページのプログラムを改良して、PUT/POST を使えるようにすることはできそうですよね?
- 当然、Firebase のproject も皆さんが作ったものを利用するようにしてくれないと、困りますが。
- 今回のscores_coroutine.py を真似れば、カレンダーっぽいものも作れそうな気がしませんか?例えば、こんな感じ。
- 上には、共有カレンダー一覧を表示
- 下には、選んだカレンダーの一覧を表示
- あるいは、event 入力フォームも追加して、アカウントに登録。
- お絵かきツールの絵の内容(整数4つ組のリスト)を、クラウドに保存したり、クラウドから持ってきたりする拡張を加えてみる。
別に、なんか手が届きそうな気がしませんが? 課題的には、1. だけでも一応合格扱いになるし、2, 3, みたいな拡張入れれば、色々派手目なアプリになる気がしませんか?