コンポーネント配置とイベント処理
プログラムの紹介
まずは簡単なプログラムの紹介。
コンポーネントとその配置
いくつかの部品が並んでいます。
- Text: テキストを表示するだけ
- Input: テキスト入力をする場所
- 状態としてテキストを持つ
- Button: ボタン
- ボタンを押された際に event 処理
- ListBox: 複数項目を表示
- 状態として複数のテキスト要素を持つ
- 行選択時に event 処理可能
- MultiLine: 複数行を表示
- 状態として複数行にわたるテキストを持つ
各部品は、TkEasyGUI のコンポーネントで、こんな感じに作成可能。
import TkEasyGUI as eg
my_input = eg.Input('ccc')
一方で、複数要素を縦横に並べる際は、layout に部品の並べ方を指定し、window にします。
my_input
, my_listbox
, my_multiline
は、後で関数から参照するので、変数名を割り当ててあります。
class SampleA:
my_time = eg.Text(str(datetime.datetime.now()))
my_input = eg.Input('ccc')
my_listbox = eg.Listbox(values=['aaa', 'bbb'],
expand_x=False, expand_y=True, size=(30, 10))
my_multiline = eg.Multiline('', size=(30, 15), background_color='lightblue')
layout1 = [
[eg.Text('Add entry:'), my_input, # my_input は上で作成した入力欄
eg.Button('add', key='btn_add', background_color='blue', color='white')],
# add ボタンの event は btn_add
[my_listbox], # 先ほど作った listbox
[eg.Button('remove', key='btn_remove', background_color='orange', color='white')],
# remove ボタンの event は btn_add
[eg.Text('log:')],
[my_multiline] # 先ほど作った multiline
]
window = eg.Window('SampleA', layout1)
Event 処理
上に述べたように、いくつかのコンポーネントは、コンポーネント内で起こった Event を処理することができます。
key
は 後で event を識別するために使います。こちらは、add
ボタンの例です。
eg.Button('add', key='btn_add', background_color='blue', color='white')
で、Event の処理ですが、window 毎に GUI 処理ループを書いて、そこで処理する形になっています。
self.window.read()
は、event が来るのを寝てまっている感じです。
テキスト入力待ちの input()
などと一緒ですね。
event
で、起きた event を識別します。先ほどの add
ボタンでは btn_add'
としましたよね。
event に関連した情報(例えば、listbox でクリックされたのは、何番目の要素か?とか)は、values
に入っています。プログラムを実行して、print()
の結果みてみてください。
def main(self):
while True:
event, values = self.window.read() # Event 待ち
if event == eg.WIN_CLOSED:
break
print(f"event='{event}', code={ord(event[0])}, values={values}\n")
if event == 'btn_add':
self.add_line()
if event == 'btn_remove':
self.del_lines()
self.window.close()
各メソッドがイベント処理として何をしているのかは、一例だけ紹介します。
add_line()
は、要素を追加するためのボタンを押したときの処理ですね。
def add_line(self):
word = self.my_input.get()
lines = self.my_listbox.values
lines.append(word)
self.my_listbox.update(lines)
self.add_log('add: ' + word)
my_input
のテキスト(word
)を取得しmy_listbox
の要素を取得して、word
を追加my_listbox
に反映させる- ついでに、ログ表示に追記
my_input, my_listbox
を変数に割り当ててたのは、こんな感じに関数からのアクセスを容易にするためです。
コンポーネントの配置2
部品が増えてくると、レイアウトも複雑にしたいですよね。
simpleC.py は、simpleA
と、次ページで紹介する描画系simpleB
を window にまとめたモノです。
Frame というのを使って階層的に構成すれば、あまり苦労しなくても大丈夫です。
layout1 = [ .... さきほどと一緒 ....]
layout2 = [ .... 同様 ....]
layout = [
[eg.Frame('frameA', layout1), eg.Frame('frameB', layout2)]
]
window = eg.Window('SampleC', layout)
定期的処理
GUI のプログラムを書いていると、定期的におこないたい処理などもあります。 例えば、時計を進めるとか、敵キャラを動かすとか。
TkEasyGUI では、event 待ちに time out 設定をすることで、GUI event が起きない時も、
代わりに timeout
event を起こして、その処理を書くことができます。以下では、1秒ごとに時間表示を更新しています。正確に1秒ごとに実行される訳ではないですが、気になるなら timeout を適時調整してもらってもよいかと。
event, values = self.window.read(timeout=1000, timeout_key='timeout') # Event 待ち
if event == 'timeout':
self.my_time.update(str(datetime.datetime.now()))