1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめてのアドベントカレンダーAdvent Calendar 2024

Day 13

tkinter を使った複数個ある bind を loop で処理する方法

Posted at

tkinterで複数個のボタンの配置

tkinter を使っていて、ボタンなど同じ物を複数個作成する際、1 つずつ作成していると面倒なので、loop を使って以下のような方法をとると思います。

import tkinter as tk


root = tk.Tk()
buttons = []
# 5つのボタンを追加
for i in range(0,5):
    buttons.append(tk.Button(root, text=f"{i}番目のボタン"))
    buttons[i].pack()

root.mainloop()

bind処理の追加

ここに bind で右クリック処理を付けます。

import tkinter as tk
+ from tkinter import messagebox


+ # クリック関数
+ def click(event):
+     messagebox.showinfo("情報", "クリックしました")
+     return


root = tk.Tk()
buttons = []
# 5つのボタンを追加
for i in range(0, 5):
    buttons.append(tk.Button(root, text=f"{i}番目のボタン"))
    buttons[i].pack()
+     # bind 処理追加 右クリックに処理を付ける
+     buttons[i].bind("<Button-3>", click)

root.mainloop()

ただ、これでは何番目のボタンをクリックしたかわかりません。
lambda 関数を使えば関数に引数を渡せるため上手くいきそうです。

import tkinter as tk
from tkinter import messagebox


# クリック関数
- def click(event):
-     messagebox.showinfo("情報", "クリックしました")
+     def click(event, i):
+     messagebox.showinfo("情報", f"{i}をクリックしました")
return


root = tk.Tk()
buttons = []
# 5つのボタンを追加
for i in range(0, 5):
    buttons.append(tk.Button(root, text=f"{i}番目のボタン"))
    buttons[i].pack()
    # bind 処理追加 右クリックに処理を付ける
+     # lambda 関数で引数を渡す
-     buttons[i].bind("<Button-3>", click)
+     buttons[i].bind("<Button-3>", lambda event: click(event, i))
root.mainloop()

実行すると、確かに「4 をクリックしました」と表示されるので、値が送られています。ただ、どこを押しても「4 をクリックしました」となってしまいます。
これは、ボタンをクリックした際に i の値を参照するためで、(クリックするときは 5 つのボタンが作成された後であるため)i の値 4 がすべてのボタンで表示されてしまっています。

解消方法

この現象を回避するためにヘルパー関数を間に挟むことで解消できます。

import tkinter as tk
from tkinter import messagebox


# クリック関数
def click(event, i):
    messagebox.showinfo("情報", f"{i}をクリックしました")
    return


+ # ヘルパー関数
+ def helper_lambda(i):
+     return lambda event: click(event, i)


root = tk.Tk()
buttons = []
# 5つのボタンを追加
for i in range(0, 5):
    buttons.append(tk.Button(root, text=f"{i}番目のボタン"))
    buttons[i].pack()
    # bind 処理追加 右クリックに処理を付ける
-     # lambda 関数で引数を渡す
+     # ヘルパー関数を通してクリック関数を呼び出す
-     buttons[i].bind("<Button-3>", lambda event: click(event, i))
+     buttons[i].bind("<Button-3>", helper_lambda(i))
root.mainloop()

これで、押された番号の i を参照することができました。

今回の最終コード
import tkinter as tk
from tkinter import messagebox


# クリック関数
def click(event, i):
    messagebox.showinfo("情報", f"{i}をクリックしました")
    return


# ヘルパー関数
def helper_lambda(i):
    return lambda event: click(event, i)


root = tk.Tk()
buttons = []
# 5つのボタンを追加
for i in range(0, 5):
    buttons.append(tk.Button(root, text=f"{i}番目のボタン"))
    buttons[i].pack()
    # bind 処理追加 右クリックに処理を付ける
    # ヘルパー関数を通してクリック関数を呼び出す
    buttons[i].bind("<Button-3>", helper_lambda(i))
root.mainloop()

参考: https://stackoverflow.com/questions/14259072/tkinter-bind-function-with-variable-in-a-loop

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?