KURORO BLOGのロゴ

このエントリーをはてなブックマークに追加
【コード付】Tkinterで使われるbindとは?bindの仕組みを交えて解説

【コード付】Tkinterで使われるbindとは?bindの仕組みを交えて解説

今回はTkinterで使われるbindに関して、bindの仕組みを交えて徹底解説いたします。なんとなくbindを使っていた、bindの仕組みを理解して、知見を深めたい方へおすすめです。ぜひ最後までご一読ください。

目次
  1. そもそもTkinterで使われるbindとは?
    1. そもそもTkinterで使われるイベントとは?
    2. bindの仕組み
  2. tkinterで使われるbind関数の定義
    1. 下準備
    2. sequence
    3. func
    4. add
  3. bind関数を削除する
  4. 関数に渡されるイベント情報を一挙紹介
    1. num
    2. x, y
    3. time
    4. char
    5. keysym
    6. widget
    7. keysym_num, keycode
    8. x_root, y_root
    9. type
  5. 全てのWidgetにbind関数を適用する
  6. bind関数の代わりにcommand optionを利用する
  7. まとめ
  8. 参考文献
目次を開く⬇︎

そもそもTkinterで使われるbindとは?

Tkinterで使われるbindとは、イベントと関数の実行を紐付けるものを意味します。

別名でbind関数と呼ばれます。Tkinterを活用する上で非常に大切な関数になります。

そもそもTkinterで使われるイベントとは?

Tkinterで使われるイベントとは、

  • Tkinterのアプリ内でボタンを選択する
  • Tkinterのアプリ内で文字を入力する
  • Tkinterのアプリ内でマウスを動かす

などの動作を意味します。

まとめると、Tkinterで活用されるbindとは、何か動作(ボタンを選択する、文字を入力するなど)が起こった場合に、関数の実行を手助けするものを意味します。

少しずつ歩みを進めていますが、謎は解けてきていますでしょうか?以下の「bindの仕組み」を確認しながら、さらに理解を深めましょう。

bindの仕組み

画像からわかる通り、bindの仕組みは、

  • 「ユーザー」、「bind関数」、「関数」で構成される
  • 始めにユーザーからイベント(画像の場合、ボタンを選択)を実行します
  • イベント(画像の場合、ボタンを選択)が実行されると「bind関数」が働きます
  • 「bind関数」によって、イベント(画像の場合、ボタンを選択)に紐づく関数を実行します

で成り立ちます。

以上のことから橋渡しするためにも、bind関数は必要になります。

tkinterで使われるbind関数の定義

bind関数は、

1# 第一引数 : sequence(イベント内容(ボタンを選択する、文字を入力するなど)を設定)
2# 第二引数 : func(第一引数のイベント内容(ボタンを選択する、文字を入力するなど)が実行された場合に、呼ばれる関数を設定)
3# 第三引数(任意) : add('+' or ''(デフォルト)を設定する。一つ前に宣言されるbind関数を実行するのか設定するために利用される。)
4# ''の場合、一つ前のbind関数で宣言された関数(第二引数)を実行しないで、今回bindする関数を実行する。
5# '+'の場合、一つ前のbind関数で宣言された関数(第二引数)を実行して、今回bindする関数を実行する。
6# 戻り値 : bind関数に紐づく独自ID
7.bind(sequence, func, add)

で定義されます。戻り値としてbind関数に紐づく独自IDが返されます。独自IDbind関数を削除するために利用します。

またbind関数は全てのWidgetに対応可能です。

Widgetに関しては、【初学者必見!?】Tkinterで使われるlabelの活用方法を徹底解説の「Tkinterの構成要素」でまとめていますので、是非ご確認ください。

bind関数の各引数の詳細を説明する前に、まずは下準備を行いましょう。

下準備

下準備以降のbind関数の説明に関して、以下のコードを通して解説して参ります。コードを確認してみてください。できればコードに触れて、一緒にbind関数を実装しましょう。

1import tkinter as tk
2
3class Application(tk.Frame):
4    # 関数に紐づく、イベントの詳細情報を取得する関数
5    # event : イベント詳細情報
6    def getEventDetail(self, event):
7        print(event.keysym)
8
9    # 追加bind用の関数。実行される場合に、hello worldを出力する。
10    def getAddFunc(self, event):
11        print('hello world')
12
13    def __init__(self, master=None):
14        # Windowの初期設定を行う。
15        super().__init__(master)
16
17        # Windowの画面サイズを設定する。
18        # geometryについて : https://kuroro.blog/python/rozH3S2CYE0a0nB3s2QL/
19        self.master.geometry("300x200")
20
21        # Windowを親要素として、label Widgetを作成する。
22        # text : テキスト情報
23        # bg : 背景色を設定
24        # 色について : https://kuroro.blog/python/YcZ6Yh4PswqUzaQXwnG2/
25        # Labelについて : https://kuroro.blog/python/Pj4Z7JBNRvcHZvtFqiKD/
26        label = tk.Label(self.master, text="test", bg='blue')
27
28        # イベントと関数の実行を紐づける。
29        # 第一引数 : イベント内容。label Widgetがクリックされた場合
30        # 第二引数 : 第一引数が実行された場合に、呼び出す関数。self.getEventDetailとする。
31        # 戻り値 : bind関数に紐づく独自ID
32        label.bind("<ButtonPress>", self.getEventDetail)
33        # イベントと関数の実行を紐づける。
34        # 第一引数 : イベント内容。label Widgetがクリックされた場合
35        # 第二引数 : 第一引数が実行された場合に、呼び出す関数。self.getAddFuncとする。
36        # 第三引数 : ''か'+'を指定する。(デフォルト : '')
37        # ''の場合、一つ前のbind関数で宣言された関数を実行しないで、今回bindする関数を実行する。今回の場合、self.getEventDetailを実行しないで、self.getAddFuncを実行する。
38        # '+'の場合、一つ前のbind関数で宣言された関数を実行して、今回bindする関数を実行する。今回の場合、self.getEventDetailを実行して、self.getAddFuncを実行する。
39        # 戻り値 : bind関数に紐づく独自ID
40        label.bind("<ButtonPress>", self.getAddFunc, '+')
41
42        # Windowを親要素とした場合に、label Widgetをどのように配置するのか?
43        # packについて : https://kuroro.blog/python/UuvLfIBIEaw98BzBZ3FJ/
44        label.pack()
45
46
47# Tkinter初学者参考 : https://docs.python.org/ja/3/library/tkinter.html#a-simple-hello-world-program
48if __name__ == "__main__":
49    # Windowを生成する。
50    # Windowについて : https://kuroro.blog/python/116yLvTkzH2AUJj8FHLx/
51    root = tk.Tk()
52    app = Application(master=root)
53
54    # Windowをループさせて、継続的にWindow表示させる。
55    # mainloopについて : https://kuroro.blog/python/DmJdUb50oAhmBteRa4fi/
56    app.mainloop()

sequence

sequenceではイベント内容(ボタンを選択する、文字を入力するなど)を設定します。

sequenceの値は文字列で指定し、次のような形式で入力します。

<modifier-type-detail>

  • modifier : イベントの条件を設定する。(例) Shiftキーを押しながらボタンを選択する, Controlキーを押しながらボタンを選択するなど。
  • type : イベントの種類。(例) ボタンが押された, ボタンからマウスが離れたなど。
  • detail : イベントの種類の詳細。(例) 特定のボタンが押された、特定のキーが押されたなど。

文字列の種類に関しては、以下の表にまとめましたので、是非ご確認ください。

type意味利用可能なmodifier利用可能なdetail利用例(下準備に対応)
Button, ButtonPress               ボタンが押された                 Shift, Control, Alt, Lock, Double, Triple, Button1 または B1, Button2 または B2, Button3 または B3, Button4 または B4, Button5 または B5-N(Nは数字)を付加することで特定のボタンを指定できる。     label.bind("<ButtonPress>", self.getEventDetail), label.bind("<Shift-Button-1>", self.getEventDetail)
ButtonReleaseマウスがボタンから離れたShift, Control, Alt, Lock, Double, Triple, Button1 または B1, Button2 または B2, Button3 または B3, Button4 または B4, Button5 または B5-N(Nは数字)を付加することで特定のボタンを指定できる。label.bind("<ButtonRelease>", self.getEventDetail)
Key, KeyPressキーが押されたShift, Control, Alt, Lock, Double, Triple, Button1 または B1, Button2 または B2, Button3 または B3, Button4 または B4, Button5 または B5-K(Kは文字)を付加することで特定のキーを指定できる。label.bind("<KeyPress>", self.getEventDetail), label.bind("<Control-Key-a>", self.getEventDetail)
KeyReleaseキーから離れたShift, Control, Alt, Lock, Double, Triple, Button1 または B1, Button2 または B2, Button3 または B3, Button4 または B4, Button5 または B5-K(Kは文字)を付加することで特定のキーを指定できる。label.bind("<KeyRelease>", self.getEventDetail)
Motionマウスの移動Shift, Control, Alt, Lock, Double, Triple, Button1 または B1, Button2 または B2, Button3 または B3, Button4 または B4, Button5 または B5xlabel.bind("<Motion>", self.getEventDetail)
Enterマウスカーソルが画面内に入ったShift, Control, Alt, Lock, Double, Triple, Button1 または B1, Button2 または B2, Button3 または B3, Button4 または B4, Button5 または B5xlabel.bind("<Enter>", self.getEventDetail)
Leaveマウスカーソルが画面から外れたShift, Control, Alt, Lock, Double, Triple, Button1 または B1, Button2 または B2, Button3 または B3, Button4 または B4, Button5 または B5xlabel.bind("<Leave>", self.getEventDetail)

※ type(イベント)の種類一覧を確認したい場合、以下のようにコードを記述してご確認ください。

1import tkinter
2# type(イベント)の種類一覧を表示
3print(tkinter.EventType.__members__)

以下print(tkinter.EventType.members)の出力結果です。

func

funcではイベント内容(ボタンを選択する、文字を入力するなど)が実行された場合に、呼ばれる関数を設定します。

funcの値は、次のように関数名を指定します。

1def 関数名(event):    
2    # 処理
3    # ...
4    # ...
5  
6label.bind("<modifier-type-detail>", 関数名)

add

addでは一つ前に宣言されるbind関数を実行するのか設定できます。

addの値として、'' or '+'を指定できます。(''はデフォルト)

''の場合、一つ前のbind関数で宣言された関数(以下のコードだと関数A)を実行しないで、今回bindする関数(以下のコードだと関数B)を実行します。

反対に'+'の場合、一つ前のbind関数で宣言された関数(以下のコードだと関数A)を実行して、今回bindする関数(以下のコードだと関数B)を実行します。

1def 関数A(event):    
2    # 処理
3    # ...
4    # ...
5
6def 関数B(event):    
7    # 処理
8    # ...
9    # ...
10  
11label.bind("<modifier-type-detail>", 関数A)
12label.bind("<modifier-type-detail>", 関数B, '') or label.bind("<modifier-type-detail>", 関数B, '+')

bind関数を削除する

bind関数を削除するためには、unbind関数の利用が必要です。

unbind関数は、

1# 第一引数 : sequence(イベント内容(ボタンを選択する、文字を入力するなど)を設定)
2# 第二引数 : bind関数に紐づく独自ID
3# 戻り値 : なし
4.unbind(sequence, id)

で定義されます。戻り値はありません。

例えば以下のようなコードを作成して、

1import tkinter as tk
2
3class Application(tk.Frame):
4    # 関数に紐づく、イベントの詳細情報を取得する関数
5    # event : イベント詳細情報
6    def getEventDetail(self, event):
7        print(event.keysym)
8
9    def __init__(self, master=None):
10        # Windowの初期設定を行う。
11        super().__init__(master)
12
13        # Windowの画面サイズを設定する。
14        # geometryについて : https://kuroro.blog/python/rozH3S2CYE0a0nB3s2QL/
15        self.master.geometry("300x200")
16
17        # Windowを親要素として、label Widgetを作成する。
18        # text : テキスト情報
19        # bg : 背景色を設定
20        # 色について : https://kuroro.blog/python/YcZ6Yh4PswqUzaQXwnG2/
21        # Labelについて : https://kuroro.blog/python/Pj4Z7JBNRvcHZvtFqiKD/
22        label = tk.Label(self.master, text="test", bg='blue')
23
24        # イベントと関数の実行を紐づける。
25        # 第一引数 : イベント内容。label Widgetがクリックされた場合
26        # 第二引数 : 第一引数が実行された場合に、呼び出す関数。self.getEventDetailとする。
27        # 戻り値 : bind関数に紐づく独自ID
28        id = label.bind("<ButtonPress>", self.getEventDetail)
29
30        # 登録されたbind関数を削除する。
31        # 第一引数 : sequence(イベント内容(ボタンを選択する、文字を入力するなど)を設定)
32        # 第二引数 : bind関数に紐づく独自ID
33        # 戻り値 : なし
34        label.unbind("<ButtonPress>", id)
35
36        # Windowを親要素とした場合に、label Widgetをどのように配置するのか?
37        # packについて : https://kuroro.blog/python/UuvLfIBIEaw98BzBZ3FJ/
38        label.pack()
39
40# Tkinter初学者参考 : https://docs.python.org/ja/3/library/tkinter.html#a-simple-hello-world-program
41if __name__ == "__main__":
42    # Windowを生成する。
43    # Windowについて : https://kuroro.blog/python/116yLvTkzH2AUJj8FHLx/
44    root = tk.Tk()
45    app = Application(master=root)
46
47    # Windowをループさせて、継続的にWindow表示させる。
48    # mainloopについて : https://kuroro.blog/python/DmJdUb50oAhmBteRa4fi/
49    app.mainloop()

'test'ボタンを選択すると、self.getEventDetail関数が実行されない = unbind関数によってbind関数が削除されたようになります。

関数に渡されるイベント情報を一挙紹介

bind関数を用いてイベントから関数を実行すると、実行される関数の引数へイベント情報が付与されます。

1# 関数の場合
2def 関数名(event):
3    # イベント情報
4    print(event)
5    ...
6    ...
7
8# クラスメソッドの場合
9# クラスメソッドとは? : https://techacademy.jp/magazine/40330#:~:text=%E3%82%AF%E3%83%A9%E3%82%B9%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%20%E3%81%A8%E3%81%AF%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AB%E7%B4%90%E3%81%A5%E3%81%91%E3%82%89%E3%82%8C%E3%81%9F,%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AB%E8%A8%98%E8%BF%B0%E3%81%97%E3%81%BE%E3%81%99%E3%80%82
10def 関数名(self, event):
11    # イベント情報
12    print(event)
13    ...
14    ...

実際にどのような内容が書き込まれているのか、イベント情報を一挙にご紹介いたします。

num

マウスボタンの番号を取得できます。

例えば下準備コードのprint(event.keysym)箇所を、以下のように変更すると、

1print(event.num)

以下の画像のようにマウスボタンの番号を取得できます。

x, y

それぞれWidgetのx座標, y座標を取得できます。

例えば下準備コードのprint(event.keysym)箇所を、以下のように変更すると、

1-    print(event.keysym)
2+    print(event.x)
3+    print(event.y)

以下の画像のようにlabel Widgetのx座標, y座標を取得できます。

time

イベントの発生時刻をタイムスタンプで取得できます。

例えば下準備コードのprint(event.keysym)箇所を、以下のように変更すると、

1print(event.time)

以下の画像のようにイベントの発生時刻を取得できます。

char

キーに対応する文字を取得できます。

例えば下準備コードのprint(event.keysym)箇所を、以下のように変更すると、

1print(event.char)

キーに対応する文字を取得できます。

keysym

キーに対応する名前を取得できます。

widget

イベントを実行したWidgetの名前を取得できます。

例えば下準備コードのprint(event.keysym)箇所を、以下のように変更すると、

1print(event.widget)

以下の画像のようにイベントを実行したlabel Widgetの名前を取得できます。

keysym_num, keycode

キーに対応する名前を数字で取得できます。

例えば下準備コードのprint(event.keysym)箇所を、以下のように変更すると、

1print(event.keysym_num)

キーに対応する名前を数字で取得できます。

x_root, y_root

それぞれWindowのx座標, y座標を取得できます。

例えば下準備コードのprint(event.keysym)箇所を、以下のように変更すると、

1-   print(event.keysym)
2+   print(event.x_root)
3+   print(event.y_root)

以下の画像のようにWindowのx座標, y座標を取得できます。

type

イベントを発生した要因を取得できます。

例えば下準備コードのprint(event.keysym)箇所を、以下のように変更すると、

1print(event.type)

以下の画像のようにイベントを発生した要因を取得できます。

全てのWidgetにbind関数を適用する

bind_all関数を利用すると、全てのWidgetに対して、bind関数を適用できます。

つまり一度bind_all関数を宣言すると、bind_all関数で定義するイベント内容が、Window(画面内)で実行される度に、関数の実行が行われます。

bind_all関数は、bind関数と同じく

1# 第一引数 : sequence(イベント内容(ボタンを選択する、文字を入力するなど)を設定)
2# 第二引数 : func(第一引数のイベント内容(ボタンを選択する、文字を入力するなど)が実行された場合に、呼ばれる関数を設定)
3# 第三引数(任意) : add('+' or ''(デフォルト)を設定する。一つ前に宣言されるbind関数を実行するのか設定するために利用される。)
4# ''の場合、一つ前のbind関数で宣言された関数(第二引数)を実行しないで、今回bindする関数を実行する。
5# '+'の場合、一つ前のbind関数で宣言された関数(第二引数)を実行して、今回bindする関数を実行する。
6# 戻り値 : bind_all関数に紐づく独自ID
7.bind_all(sequence, func, add)

で定義されます。戻り値として、bind_all関数に紐づく独自IDが返されます。独自IDbind_all関数を削除するために利用します。

例えば下準備コードのlabel.bind("<ButtonPress>", self.getEventDetail)箇所を、以下のように変更すると、

1label.bind_all("<ButtonPress>", self.getEventDetail)

Window(画面内)でlabel Widget以外を選択しても、関数が実行されるようになります。

bind関数の代わりにcommand optionを利用する

bind関数の代わりにcommand optionを利用しても、イベントと関数の実行を紐付けられます。

しかしcommand optionを利用できるWidgetは限られているため、

  • command optionが利用できるか調べる
  • command optionが使用できる場合、利用する
  • command optionが活用できない場合、bind関数を利用する

と手順を踏んで、活用することをおすすめします。

例えば以下のようなコードを記述して、

1import tkinter as tk
2
3class Application(tk.Frame):
4    # hello worldを出力する関数
5    def getHelloWorld(self):
6        print('hello world')
7
8    def __init__(self, master=None):
9        # Windowの初期設定を行う。
10        super().__init__(master)
11
12        # Windowの画面サイズを設定する。
13        # geometryについて : https://kuroro.blog/python/rozH3S2CYE0a0nB3s2QL/
14        self.master.geometry("300x200")
15
16        # Windowを親要素として、button Widgetを作成する。
17        # command : ボタンをクリックした時に、実行する関数を設定。self.getHelloWorldとする。
18        # text : テキスト情報
19        # Buttonについて : https://kuroro.blog/python/oFju6EngDtcYtIiMIDf1/
20        button = tk.Button(self.master, command=self.getHelloWorld, text='test')
21
22        # Windowを親要素とした場合に、button Widgetをどのように配置するのか?
23        # packについて : https://kuroro.blog/python/UuvLfIBIEaw98BzBZ3FJ/
24        button.pack()
25
26# Tkinter初学者参考 : https://docs.python.org/ja/3/library/tkinter.html#a-simple-hello-world-program
27if __name__ == "__main__":
28    # Windowを生成する。
29    # Windowについて : https://kuroro.blog/python/116yLvTkzH2AUJj8FHLx/
30    root = tk.Tk()
31    app = Application(master=root)
32
33    # Windowをループさせて、継続的にWindow表示させる。
34    # mainloopについて : https://kuroro.blog/python/DmJdUb50oAhmBteRa4fi/
35    app.mainloop()

'test'ボタンを選択するとself.getHelloWorld関数を実行して、以下の画像のように'hello world'を表示できます。

またcommand optionが利用できるか調べる場合、以下のコードを実行して

1# button Widgetの場合 : widget = tk.Button()
2widget = tk.{Widget名}()
3print(widget.keys())

option対応しているのか、ご確認ください。

buttonに関しては、Tkinterで使われるbuttonとは?コード例を交えて実践的な活用方法を解説でまとめていますので、是非ご確認ください。

まとめ

  • Tkinterで使われるbindとは、イベントと関数の実行を紐付けるものを意味します。
  • 別名でbind関数と呼ばれます。
  • bind関数は、.bind(sequence, func, add)で定義されます。

参考文献