Tkinter の使い方:利用可能なイベントやイベントが発生するタイミングを調べる

イベントの調べ方の解説ページのアイキャッチ

下記ページで Tkinter のイベント処理について解説しました。

イベント処理解説ページのアイキャッチTkinterの使い方:イベント処理を行う

Tkinter では bind 実行時に下記の形式のイベントシーケンス指定することで、「どのイベント」が発生した時にイベント処理を行うかを設定することが可能です。

イベントシーケンス
"<[modifier-]event_type[-detail]>"

event_type にはイベントの種類を記述しますが、どんなイベントがどんなタイミング(どんな操作をした時)に発生するかが具体的に分からないと何を設定すれば良いか分かりにくいですよね…。

そこで、今回は Tkinter で利用可能なイベントの種類(event_type)や、そのイベントが発生するタイミング等を調べる方法について解説したいと思います。

確かにどんなイベントがどんなタイミングで発生するのかってイマイチ分かってないんだよね…

ネット上に情報も少ないし…

英語のサイトだと詳しく説明しているところもあるようだけどね…

ただ自力で簡単に調べることもできるので、今回はその方法を解説していくよ

利用可能なイベントを調べる

Tkinter で利用可能なイベントの種類は、tkinter.EventType で列挙型(enum)として定義されています。

enum について詳しく知りたい方は別途調べていただくと良いと思いますが、要は下記により tkinter.EventType で定義されているイベントの種類を全て表示することが可能です。

イベントの種類の全表示
import tkinter
print(tkinter.EventType.__members__)

実行すると下記のような辞書形式で表示されると思います(表示結果の前半のみ載せています)。

{'KeyPress': <EventType.KeyPress: '2'>, 'Key': <EventType.KeyPress: '2'>, 'KeyRelease': <EventType.KeyRelease: '3'>, 'ButtonPress': <EventType.ButtonPress: '4'>, 'Button': <EventType.ButtonPress: '4'>, 'ButtonRelease': <EventType.ButtonRelease: '5'>, 'Motion': <EventType.Motion: '6'>,

基本的に、この辞書の各「キー名」が「イベントシーケンスの event_type に指定可能な文字列」となります。

イベントシーケンス
"<[modifier-]event_type[-detail]>"

またキー名は異なるのに、「値が同じ」ものもいくつか見られますね。

これらは異なるキー名でも、イベント処理を行うイベントの種類としては全く同じであることを示しています(どっちを指定しても良いということ)。

例えば上の表示例だと、KeyPressKeyButtonPressButton は同じイベントの種類を表すことが確認できます。

ただし、理由は分からない(バージョン要因?OS要因?)のですが、表示されるキー名全てが bind 出来るわけではないようです。

したがって、下記のように tkinter.EventType で定義されるキー名全てに対して bind に成功するかどうかを確認し、成功した場合のみキー名を表示するようにしてやれば、実際に利用可能なイベントを調べることが可能です。

利用可能なイベントの種類の全表示
import tkinter

def event_handler(event):
	pass

app = tkinter.Tk()

for event_type in tkinter.EventType.__members__.keys():
	event_seq= "<" + event_type + ">"
	try:
		app.bind_all(event_seq, event_handler)
		print(event_type)
	except tkinter.TclError:
		#print("bind error:", event_type)
		pass

app.mainloop()

実行すると下記のように bind 可能なイベントの種類が表示されるはずです)。

KeyPress
Key
KeyRelease
ButtonPress
Button
ButtonRelease
Motion
Enter
Leave
FocusIn
FocusOut

ここでは表示結果の前半のみを載せています。全て知りたい方は是非自身でスクリプトを実行して調べてみてください!

この表示されるイベント名が、利用可能なイベントシーケンスの event_type 全てになります。

スクリプトの except の print 部分のコメントアウトを外せば、どの種類のイベントが bind に失敗しているかも確認することもできます。

イベントの発生タイミングを調べる

利用可能なイベントを調べるで紹介したスクリプトでは、下記を利用可能な全イベント種類に対して行っています。

イベント処理の設定
app.bind_all(event_seq, event_handler)

したがって、下記ページで解説したように「アプリ内の全ウィジェット」に対して「全イベント」が発生した際に event_handler が実行されることになります。

イベント処理解説ページのアイキャッチTkinterの使い方:イベント処理を行う

また、イベントハンドラの引数は tkinter.Event クラスのインスタンスであり、type プロパティにはイベントハンドラを実行する引き金になったイベントの種類が格納されています(この辺りも上記ページで解説しています)。

なので、event_handler の中で引数の type プロパティを表示するようにしてやれば、イベントが発生した時にどの種類のイベントが発生したかが表示されるようになります。

これにより、アプリに対してどんな操作をすれば、どの種類のイベントが発生するかを確認することができ、各イベントの発生タイミングを調べることが可能です。

イベントハンドラを利用したイベント発生タイミングの表示

ここまでの解説を踏まえ、イベントの発生タイミングを調べるスクリプトは下記のようになります。

イベント発生タイミング
# -*- coding:utf-8 -*-
import tkinter

# イベントハンドラ
def event_handler(event):
	print(event.type)


app = tkinter.Tk()
app.title("イベント")

# 利用可能なイベントを全てbind
for event_type in tkinter.EventType.__members__.keys():
	event_seq= "<" + event_type + ">"
	try:
		app.bind_all(event_seq, event_handler)
		#print(event_type)
	except tkinter.TclError:
		#print("bind error:", event_type)
		pass

# メインループ
app.mainloop()

実行するとアプリが起動し、アプリ起動時に発生するイベントの種類(ExposeMapVisibilityActivate など)が表示されると思います。

さらに、アプリ上でマウスを動かす、マウスボタンをクリックする、ウィンドウサイズを変更する、キーボードのキーを押す、などを行えば、それぞれに対応したイベントの種類が表示される(MotionButtonPressButtonReleaseConfigureExposeKeyPressKeyRelease など)と思います(特に Motion に関しては大量に表示されると思います。)。

こんな感じで、アプリに対して操作をした時に、発生したイベントの種類が表示されるので、イベントの発生タイミングを調べることが可能です。

大量にイベントの種類が表示されるのが嫌であれば、直前に発生したイベントの種類と異なる場合のみ表示するようなことも可能です。

イベント発生タイミング(表示少なめ)
# イベントハンドラ
pre_event = {}
def event_handler(event):
	global pre_event
	now_event = {}
	now_event['type'] = event.type
	if now_event != pre_event:
		print(event.type)
		pre_event['type'] = event.type

スポンサーリンク

イベントの詳細を調べる

イベントの発生タイミングを調べるで紹介したスクリプトではイベントの発生タイミングを表示するだけでしたが、イベントハンドラの引数 eventプロパティを表示することで、発生したイベントの詳細を調べることも可能です。

例えば下記スクリプトでは、どのウィジェットに対するイベントが発生したかを widget を、どのキーが押されたかを keysym をそれぞれ表示することで確認できるようにしています。

イベントの詳細を調べる
# -*- coding:utf-8 -*-
import tkinter

# イベントハンドラ
pre_event = {}
def event_handler(event):
	global pre_event
	now_event = {}
	now_event["type"] = event.type
	now_event["widget"] = event.widget
	now_event["keysym"] = event.keysym
	
	# 前回と異なるイベントの場合のみ表示
	if now_event != pre_event:
		print(
			"type:" + str(event.type),
			"widget" + str(event.widget),
			"keysym:" + event.keysym,
		)
		
		pre_event["type"] = event.type
		pre_event["widget"] = event.widget
		pre_event["keysym"] = event.keysym

app = tkinter.Tk()
app.geometry("620x550")
app.title("イベント")

# まずはてきとうにウィジェットを配置
button = tkinter.Button(
	app,
	width=10,
	height=2,
	text="ボタン",
)
button.pack()

canvas = tkinter.Canvas(
	app,
	width=100,
	height=100,
	bg="red"
)
canvas.pack()

label = tkinter.Label(
	app,
	width=10,
	height=2,
	text="ラベル"
)
label.pack()

# 利用可能なイベントを全てbind
for event_type in tkinter.EventType.__members__.keys():
	event_seq= "<" + event_type + ">"
	try:
		app.bind_all(event_seq, event_handler)
		#print(event_type)
	except tkinter.TclError:
		#print("bind error:", event_type)
		pass

# メインループ
app.mainloop()

実行すると下のアニメーションのように、アプリに対して操作した時などに発生したイベントの種類(type)、どのウィジェットに対するイベントか(widget)、どのキーが押されたかの情報(keysym)が表示されます。

イベントの詳細を表示する様子

widget に関してはウィジェットのインスタンス名ではなく、下記のような形式で表示されるので注意してください(複数同じ種類のウィジェットを作成した場合は最後に数字が付加される)。

!ウィジェットの種類名

また keysym に関してはキーボードに無関係のイベントでは ?? で表示されます。

今回は widget と keysym のみを表示していますが、他にも tkinter.Event のプロパティを表示することで他の情報を確認することも可能です。

プロパティにどんなものがあるかは下記ページで紹介していますので、興味のある方はこちらもご確認ください。

イベント処理解説ページのアイキャッチTkinterの使い方:イベント処理を行う

また、上記のようなスクリプトでイベントの詳細を調べることで、イベントシーケンスにどのような指定を行えば良いかを理解することもできます。

イベントシーケンスの detail について考えてみましょう。

イベントシーケンス
"<[modifier-]event_type[-detail]>"

この detail には keysym を指定してやることで、その keysym に対応するキーの Press や Release に対するイベント処理を行うことができるようになります。

なので、イベント処理を行いたいキーに対してどうdetail を指定すれば良いか分からない時は、ひとまず全イベントに対してイベント処理を設定し、イベントハンドラで keysym を表示することで 、detail に指定すべき文字列を調べることが可能です。

例えば MacOS で「Command キー」が押された時に keysym を表示すると “Meta_L” を表示されますので、「Command キー」が押された時のイベント処理を設定するには下記のようにイベントシーケンスを設定すれば良いことになります。

イベントシーケンス
"<KeyPress-Meta_L>"

こんな感じでイベントシーケンスの設定に困った時にも、イベント処理をとりあえず行い、event のプロパティを表示したりすることで何を設定すれば良いかを調べることができます。

まとめ

このページでは Tkinter で利用可能なイベントの種類や各イベントの発生タイミング・さらにはイベントの詳細を自力で調べる方法について解説しました。

Tkinter のドキュメントはネット上にも少なかったりもしますが、こんな感じで自力で調べてしまえばドキュメントなしでも自力で知識を身につけ、自由自在に GUI アプリを開発していくこともできます!

是非今回紹介した方法やスクリプトを活用して Tkinter のイベントについて調べてみてください!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です