Сначала давайте исправим ваш код, чтобы дать желаемый ответ.
import tkinter as tk
class Window(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.buttons = {}
for number in range(1, 11):
self.buttons.update({'button' + str(number): tk.Button(self, height=1, width=4, bg="grey", text=number)})
for button in self.buttons:
self.buttons[button].bind('<Button-1>', lambda event, <b>num=button[6:]</b>: self.Callback(event, num))
self.buttons[button].pack(side='left') #\____________/
def Callback(self, event, num):
print(num)
Window().mainloop()
Объяснение
Хитрость заключается в том, как работают лямбда-функции.
Когда вы пишете lambda event: self.Callback(event, button[6:])
, он не получает значение button[6:]
в этом экземпляре и не сохраняет его. Вместо этого он создает замыкание , что-то вроде примечания к себе, говорящего: « Я должен посмотреть, каково значение переменной button (итератор) в то время, когда меня называют ».
Теперь, когда цикл закончен и каждый виджет готов и настроен, и вы вызываете его, он будет искать значение кнопки в то время, которое, конечно, является последним значением итерации. (здесь button10
).
num=button[6:]
заставляет функцию сохранять текущее значение счетчика (здесь кнопка ) во время определения вашей лямбды, вместо ожидания поиска значения кнопка позже.
Кредиты: BrenBarn
Просто добавьте, что вы можете делать то, что делаете сейчас, в гораздо меньшем количестве кода, используя атрибут command
виджета Button
. Вот пример.
import tkinter as tk
class Window(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
for number in range(1, 11):
tk.Button(self, height=1, width=4, bg="grey", text=number, command=lambda num=number: self.Callback(num)).pack(side='left')
def Callback(self, num):
print(num)
Window().mainloop()