コンポーネント配置とイベント処理
プログラムの紹介
まずは簡単なプログラムの紹介。
コンポーネントとその配置
いくつかの部品が並んでいます。
- Text: テキストを表示するだけ
- Input: テキスト入力をする場所
- 状態としてテキストを持つ
- 今回は使っていないが、key 入力の度に event 処理可能
- Button: ボタン
- ボタンを押された際に event 処理
- ListBox: 複数項目を表示
- 状態として複数のテキスト要素を持つ
- 行選択時に event 処理可能
- MultiLine: 複数行を表示
- 状態として複数行にわたるテキストを持つ
各部品は、PySimpleGUI のコンポーネントで、こんな感じに作成可能。
import PySimpleGUI as sg
my_input = sg.Input('ccc')
一方で、複数要素を縦横に並べる際は、layout に部品の並べ方を指定し、window にします。
layout1 = [
[sg.Text('Add entry:')],
[my_input, sg.Button('add', key='btn_add', bind_return_key=True)],
# my_input は上で作成した入力欄
[my_listbox], # 同様に作った listbox
[sg.Button('remove', key='btn_remove')],
[my_multiline] # 同様に作った multiline
]
window = sg.Window('Image', layout1)
Event 処理
上に述べたように、いくつかのコンポーネントは、コンポーネント内で起こった Event を処理することができます。
コンポーネント作成時に、オプションをつけて、event の有効化 (enable_events=True
)と event の key
を設定しています。
key
は 後で event を識別するために使います。以下はListBox の場合。
上のボタンの例では、event は元々有効になっていて、key
のみ設定していました。
my_listbox = sg.Listbox(values=['aaa', 'bbb'],
expand_x=False, expand_y=True, size=(30, 10),
enable_events=True, key='listbox')
で、Event の処理ですが、window 毎に GUI 処理ループを書いて、そこで処理する形になっています。
注意してほしいのは、self.window.read()
は、別に event が来るのを寝てまっている感じです。テキスト入力待ちの input()
などと一緒ですね。
event に関連した情報(例えば、listbox でクリックされたのは、何番目の要素か?とか)は、values
に入っています。プログラムを実行して、print()
の結果みてみてください。
def main(self):
while True:
event, values = self.window.read() # Event 待ち
if event == sg.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()
if event == 'listbox':
self.listbox_click(values['listbox'])
self.window.close()
各メソッドがイベント処理として何をしているのかは、一例だけ紹介します。
add_line()
は、要素を追加するためのボタンを押したときの処理ですね。
def add_line(self):
vals = self.my_listbox.Values
vals.append(self.my_input.get())
self.my_listbox.update(vals)
self.my_listbox.set_vscroll_position(100.0)
- 現在の
my_listbox
の要素を取得し(vals: list
)、 my_input
のテキストも取得して、vals
に加えmy_listbox
の要素更新をおこない、- スクロールバーも最後に
my_input, my_listbox
を変数に割り当ててたのは、アクセスを容易にするためです。
コンポーネントの配置2
部品が増えてくると、レイアウトも複雑にしたいですよね。
simpleC.py は、simpleA
と、次ページで紹介する描画系simpleB
を window にまとめたモノです。
Frame というのを使って階層的に構成すれば、あまり苦労しなくても大丈夫です。
layout1 = [ .... さきほどと一緒 ....]
layout2 = [ .... 同様 ....]
layout = [
[sg.Frame('frameX', layout1), sg.Frame('frameY', layout2)]
]
window = sg.Window('Image', layout)