Есть ли способ изменить изображение итеративно созданной кнопки при нажатии на нее? [дубликат]

Кнопки создаются в большом цикле, проходящем через 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')
Другие вопросы по тегам