【Python tkinter】クリックされたボタンを関数内で判別しテキスト情報などを取得する(bind,event)

時計 2021.02.14 / 時計

【Python tkinter】クリックされたボタンを関数内で判別しテキスト情報などを取得する(bind,event)

本記事ではPythonのtkinterで作成したGUIアプリにおける、クリックされたボタンウィジェットを関数内で判別・テキストや属性値を取得する方法について解説していきます。

本記事で紹介している方法はbind()メソッドを使用した方法です。
このbind()メソッドはボタンウィジェットだけでなく、すべてのウィジェットで使用できます。

そのためボタンウィジェット以外のウィジェットでも、クリックイベントの判別やテキスト情報などの取得が可能です。

本記事を通して以下の知識を学べます。

学べる知識
  • bind()メソッドの使用方法
  • コールバック関数の定義方法
  • eventオブジェクトからウィジェット情報等を取得する方法

作成するプログラム

プログラムの流れ

クリックされたウィジェット(ボタン)を判別し、テキストや属性値を取得するためのプログラム作成の流れを次に示します。

  1. 対象のウィジェットに対してbind()メソッドでコールバック関数を紐づける
  2. コールバック関数には引数にeventを指定して作成する
  3. event.widget[]でウィジェットの属性情報を取得する

上記の流れについて詳しく解説していきます。

サンプルプログラム

クリックされたボタンを関数内で判別して、テキストを取得し画面に表示するプログラムのソースコードを以下に記します。

# tkinterのインポート
import tkinter as tk
import tkinter.ttk as ttk

def print_text(event):
    text.set("クリックしたボタン : " + str(event.widget["text"]))

# rootメインウィンドウの設定
root = tk.Tk()
root.title("tkinter")
root.geometry("300x200")

# メインフレームの作成と設置
frame = ttk.Frame(root)
frame.pack(fill = tk.BOTH, padx=5, pady=10)

# StringVarのインスタンスを格納するウィジェット変数text
text = tk.StringVar(frame)
text.set("")

# 各種ウィジェットの作成
for i in range(1,6):
    button = ttk.Button(frame, text=i)
    button.bind("", print_text)
    button.pack()

label = tk.Label(frame, textvariable=text)
label.pack()

root.mainloop()

このプログラムを起動すると次の画面が表示されます。

サンプルプログラムを起動後の画面

このGUIアプリでボタン3を押すと次のように表示されます。

サンプルプログラムを起動後の画面からボタンを押下

bind()メソッドでコールバック関数を紐づける

bind()メソッドとは

Buttonウィジェットではオプション引数のcommandを使用することで定義済みの関数を紐づけることができます。

その他のウィジェットに対しても、イベント発生時に紐づけた関数を実行したい場合はbind()メソッドを使用します。

bind()メソッドはすべてのウィジェットに対してトリガーとなる特定のイベントと実行する関数(コールバック関数)の紐づけを行うことができます。

サンプルプログラムでは次のように使われています。

# 各種ウィジェットの作成
for i in range(1,6):
    button = ttk.Button(frame, text=i)
    button.bind("", print_text)
    button.pack()

構文と引数

bind()メソッドでウィジェットに対して、イベント(操作)とコールバック関数の紐づけには次のように行います。

widget.bind(イベント, コールバック関数、addオプション)

bind()メソッドの第一引数にはコールバック関数を実行するトリガーとなるイベント(操作)を指定し、第二引数に実行する関数を指定します。

addオプションは通常は指定しません。
同一のウィジェットに対してイベントを追加したいときに指定します。

イベント

次のように様々なイベントが用意されています。

イベント 説明
<Button-1>、<ButtonPress>、<1> 左クリック
<Button-2>、<2> ホイールクリック
<Button-3>、<3> 右クリック
<Double-1> ダブルクリック
<ButtonRelease> クリックを離したとき
<KeyPress-K>、<k> kキーを入力したとき
<Control-c> Controlとcキーが押されたとき
<Enter> マウスカーソルがウィジェット内に入ったとき
<Leave> マウスカーソルがウィジェット内を出たとき
<Motion> ウィジェット内でカーソルが動いたとき

Buttonウィジェットに左クリック操作が発生したらcallbackを実行するプログラムは次のように記述します。

button = ttk.Button(frame, text="button")
button.bind("<Button-1>", callback)
button.pack()

addオプション

同一のウィジェットに対してaddオプションを指定せずにイベントをバインドすると、上書きされるため最初にバインドしたイベントとコールバック関数の紐づけはなくなります。

すでにイベントをバインドしているウィジェットに対して、イベントを追加する場合はaddオプションに”+”を指定します。

button = ttk.Button(frame, text="button")
button.bind("<Button-1>", callback)
button.bind("<ButtonRelease>", callback2, '+')
button.pack()

コールバック関数

コールバック関数の定義

次に実行されるコールバック関数を定義していきます。

イベントが発生し、コールバック関数が呼び出されると、コールバック関数にはイベントオブジェクト(event)が渡されます。

そのためコールバック関数を定義する際はeventを受け取るように定義します。

def callback(event):

サンプルプログラムでは次のようにコールバック関数は定義されています。

def print_text(event):

eventの属性

eventからはユーザーがどういったイベント(操作)を実行したかや、操作されたウィジェットの情報がわかります。

event.属性

例えばイベント発生のトリガーとなった、「キーボードのどのキーを押したのか」、「イベント発生時のマウスカーソルの座標」などがわかります。

属性 説明
widget ウィジェットの情報
num マウスボタンの番号
keysym キーのシンボル
char キーの文字
x, y マウスカーソルの座標
time イベント発生時刻

eventオブジェクトから情報の取得

ウィジェット情報の取得

イベント発生を起こしたウィジェット情報の取得にはevent.widgetを使用します。

サンプルプログラムでは次のように記述しています。

text.set("クリックしたボタン : " + str(event.widget["text"]))

event.widget["text"]でボタンウィジェットのテキストを取得しています。

クリックされたウィジェットのbg(バックグラウンド色)を取得するには次のように記述します。

event.widget["bg"]

これを使うことで、イベントを発生させたウィジェットの情報を変更できます。
例えば押したボタンの背景色を変更して、アクティブになっているボタンが見た目で判別できるようにもできます。

以下では背景色を変更させるプログラムを記します。

event.widget["bg"] = "blue"

キーボード操作の取得

イベント発生を起こした際のキーボード操作の取得にはevent.keysymを使用します。

以下にイベント発生を起こした際のキー入力を表示するサンプルプログラムを記します。

# tkinterのインポート
import tkinter as tk
import tkinter.ttk as ttk

def print_text(event):
    text.set("操作したキー : " + str(event.keysym))

# rootメインウィンドウの設定
root = tk.Tk()
root.title("tkinter")
root.geometry("300x200")

# メインフレームの作成と設置
frame = ttk.Frame(root)
frame.pack(fill = tk.BOTH, padx=5, pady=10)

# StringVarのインスタンスを格納するウィジェット変数text
text = tk.StringVar(frame)
text.set("")

# 各種ウィジェットの作成
for i in range(1,6):
    button = ttk.Button(frame, text=i)
    button.bind("", print_text)
    button.pack()

label = tk.Label(frame, textvariable=text)
label.pack()

root.mainloop()

まとめ

本記事「【Python tkinter】クリックされたボタンを関数内で判別・テキスト情報などを取得する方法(bind)」はいかがでしたか。

今回紹介したbind()メソッドは、tkinterでGUIアプリケーションを作成する上で非常に重要な部分です。

bind()メソッド、eventオブジェクトを使いこなせるように、いろいろなアプリケーションで使ってみてください。