tkinter で複数個のボタンの配置
tkinterを使っていて、ボタンなど同じ物を複数個作成する際、1 つずつ作成していると面倒なので、 を使って以下のような方法をとると思います。
text
1loop
python
1import tkinter as tk234root = tk.Tk()5buttons = []6# 5つのボタンを追加7for i in range(0,5):8 buttons.append(tk.Button(root, text=f"{i}番目のボタン"))9 buttons[i].pack()1011root.mainloop()
bind 処理の追加
ここに bind で右クリック処理を付けます。
python
1import tkinter as tk2from tkinter import messagebox # [!code ++]345 # クリック関数 # [!code ++]6 def click(event): # [!code ++]7 messagebox.showinfo("情報", "クリックしました") # [!code ++]8 return # [!code ++]91011root = tk.Tk()12buttons = []13# 5つのボタンを追加14for i in range(0, 5):15 buttons.append(tk.Button(root, text=f"{i}番目のボタン"))16 buttons[i].pack()17 # bind 処理追加 右クリックに処理を付ける # [!code ++]18 buttons[i].bind("<Button-3>", click) # [!code ++]1920root.mainloop()
ただ、これでは何番目のボタンをクリックしたかわかりません。
lambda 関数を使えば関数に引数を渡せるため上手くいきそうです。
python
1import tkinter as tk2from tkinter import messagebox345# クリック関数6 def click(event): # [!code --]7 messagebox.showinfo("情報", "クリックしました") # [!code --]8 def click(event, i): # [!code ++]9 messagebox.showinfo("情報", f"{i}をクリックしました") # [!code ++]10return111213root = tk.Tk()14buttons = []15# 5つのボタンを追加16for i in range(0, 5):17 buttons.append(tk.Button(root, text=f"{i}番目のボタン"))18 buttons[i].pack()19 # bind 処理追加 右クリックに処理を付ける20 # lambda 関数で引数を渡す # [!code ++]21 buttons[i].bind("<Button-3>", click) # [!code --]22 buttons[i].bind("<Button-3>", lambda event: click(event, i)) # [!code ++]23root.mainloop()
実行すると、確かに「4 をクリックしました」と表示されるので、値が送られています。ただ、どこを押しても「4 をクリックしました」となってしまいます。
これは、ボタンをクリックした際に i の値を参照するためで、(クリックするときは 5 つのボタンが作成された後であるため)i の値 4 がすべてのボタンで表示されてしまっています。
解消方法
この現象を回避するためにヘルパー関数を間に挟むことで解消できます。
python
1import tkinter as tk2from tkinter import messagebox345# クリック関数6def click(event, i):7 messagebox.showinfo("情報", f"{i}をクリックしました")8 return91011 # ヘルパー関数 # [!code ++]12 def helper_lambda(i): # [!code ++]13 return lambda event: click(event, i) # [!code ++]141516root = tk.Tk()17buttons = []18# 5つのボタンを追加19for i in range(0, 5):20 buttons.append(tk.Button(root, text=f"{i}番目のボタン"))21 buttons[i].pack()22 # bind 処理追加 右クリックに処理を付ける23 # lambda 関数で引数を渡す # [!code --]24 # ヘルパー関数を通してクリック関数を呼び出す # [!code ++]25 buttons[i].bind("<Button-3>", lambda event: click(event, i)) # [!code --]26 buttons[i].bind("<Button-3>", helper_lambda(i)) # [!code ++]27root.mainloop()
これで、押された番号の i を参照することができました。
今回の最終コード
python
1import tkinter as tk2from tkinter import messagebox345# クリック関数6def click(event, i):7 messagebox.showinfo("情報", f"{i}をクリックしました")8 return91011# ヘルパー関数12def helper_lambda(i):13 return lambda event: click(event, i)141516root = tk.Tk()17buttons = []18# 5つのボタンを追加19for i in range(0, 5):20 buttons.append(tk.Button(root, text=f"{i}番目のボタン"))21 buttons[i].pack()22 # bind 処理追加 右クリックに処理を付ける23 # ヘルパー関数を通してクリック関数を呼び出す24 buttons[i].bind("<Button-3>", helper_lambda(i))25root.mainloop()
