การสร้างปุ่ม Tkinter จำนวนมากในลูป For Loop สามารถทำได้โดยสร้าง Widget ภายในลูปและจัด Layout ด้วย pack(), grid() หรือ place() ต้องระวังปัญหา Late Binding ของ Lambda
ตัวอย่างโค้ด
from tkinter import *
from tkinter import ttk
win = Tk()
win.geometry("750x250")
labelframe = LabelFrame(win)
canvas = Canvas(labelframe)
canvas.pack(side=RIGHT, fill=BOTH, expand=1)
labelframe.pack(fill=BOTH, expand=1, padx=30, pady=30)
# สร้างปุ่ม 5 ปุ่มใน Canvas
for i in range(5):
ttk.Button(canvas, text="Button " + str(i)).pack()
win.mainloop()
ปัญหา Late Binding และวิธีแก้
# ❌ ผิด - ทุกปุ่มจะแสดงค่า i สุดท้าย (4)
for i in range(5):
btn = ttk.Button(canvas, text=f"Button {i}", command=lambda: print(i))
btn.pack()
# ✅ ถูก - capture ค่า i ด้วย default argument
for i in range(5):
btn = ttk.Button(canvas, text=f"Button {i}", command=lambda i=i: print(i))
btn.pack()
# ✅ ใช้ functools.partial
from functools import partial
for i in range(5):
btn = ttk.Button(canvas, text=f"Button {i}", command=partial(print, i))
btn.pack()
# ✅ ใช้ฟังก์ชัน factory
def make_callback(idx):
return lambda: print(idx)
for i in range(5):
btn = ttk.Button(canvas, text=f"Button {i}", command=make_callback(i))
btn.pack()
การเก็บ Reference ของปุ่ม
buttons = []
for i in range(5):
btn = ttk.Button(canvas, text=f"Button {i}", command=lambda i=i: print(i))
btn.pack()
buttons.append(btn) # เก็บไว้เพื่อควบคุมภายหลัง (disable, destroy, etc.)
# ตัวอย่าง: ปิดปุ่มทุกตัว
for btn in buttons:
btn.config(state=DISABLED)
การจัด Layout แบบ Grid
for i in range(6):
row, col = divmod(i, 3)
ttk.Button(canvas, text=f"Btn {i}").grid(row=row, column=col, padx=5, pady=5)
การประยุกต์ใช้
เหมาะสำหรับ: Keypad ตัวเลข, เมนูตัวเลือกหลายรายการ, ปุ่มฟังก์ชัน (F1-F12), Keyboard layout, Dynamic UI จากข้อมูล database/config