Есть ли способ изменить изображение итеративно созданной кнопки при нажатии на нее? [дубликат]
Кнопки создаются в большом цикле, проходящем через i, затем j, со следующим кодом:
btn[i][j] = Button(lbl_frm, width=24, height=24, image=unchecked_img,
command=lamda:change_btn_img(btn[i][j]),relief=SOLID)
global state
state = "unchecked"
btn[i][j].place(relx=.5, rely=.5, anchor='c')
с функцией изменения конфигурации кнопки:
def change_btn_img(btn):
global state
if state == "checked":
btn.configure(image=unchecked_img)
state = "unchecked"
elif state == "unchecked":
btn.configure(image=checked_img)
state = "checked"
Однако это не работает, как если бы я нажимал любую кнопку, это изменяет только изображение btn[i][j], где i и j были значениями, достигнутыми на последней итерации цикла. Кнопки используются для формирования сетки, и в этом случае щелчок по любому изменяет последний элемент в последней строке. Есть ли способ сделать так, чтобы i и j, используемые при объявлении команды при создании кнопки, были привязаны к этой конкретной кнопке?
1 ответ
Это обычная проблема с
loop
.
Вы должны задавать аргументы в
lambda
(т.е.
x
,
y
), и он будет копировать значения из, вместо использования ссылок на
i
,
j
command=lamda x=i, y=j:change_btn_img(btn[x][y])
КСТАТИ:
В Python вы можете создавать собственные атрибуты в классе, поэтому, возможно, вам следует оставить
Button
btn[i][j].state = "unchecked"
и тогда тебе не нужно
global
и каждая кнопка имеет свой
state
Или, может быть, вам стоит создать собственный
Widget
- что-то вроде этого:
class MyButton(tkinter.Button):
def __init__(self, parent, *args, **kwars):
super().__init__(parent, width=24, height=24, image=unchecked_img, command=self.change, relief=tkitner.SOLID)
self.state = "unchecked"
def change(self):
if self.state == "checked":
self.configure(image=unchecked_img)
self.state = "unchecked"
elif self.state == "unchecked":
self.configure(image=checked_img)
self.state = "checked"
а позже вы могли просто использовать
btn[i][j] = MyButton(lbl_frm)
btn[i][j].place(relx=.5, rely=.5, anchor='c')