-1

I'm using a dictionary to store my buttons as you can see in the main method. The 'self.tables' is a list with the names of tables. Therefore 'i' in the for loop is the name of a table, which is shown on the button as text. Each button should have a different command as you can see below, self.edit(i). But when you press a specific button instead of running self.edit(i), what is always run is the most recent iteration of i instead of the i that was used when the specific button was created.

    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        self.controller = controller
        self.title = Label(self, text="", font=("arial", 20))
        self.title.grid(row=0, column=0)
        self.table = ""
        self.widgetdata = {}

    def main(self):
        for x in self.widgetdata:
            self.widgetdata[x].grid_forget()

        self.tables = GuiSetup.tbls
        self.title["text"] = "Select table to edit:"
        for j,i in enumerate(self.tables):
            self.widgetdata[i] = Button(self, text=i, command=lambda: self.edit(i)) # When any of these buttons are pressed the most recent button command is run

            self.widgetdata[i].grid(row=j+1, column=0)

        self.controller.show_frame("Edit Menu")

    # Sets up the Editmenu gui for editing the specified table
    def edit(self, table, id="new"):
        print(table)
        self.table = table
        self.id = id

The code above is a section of a class and its methods. I have no idea why this is happening because the text on all of the buttons is unique but the command of each button is not what it was set to. Any suggestions would be appreciated. Thanks

Rhys J
  • 50
  • 7

1 Answers1

1

Replace

self.widgetdata[i] = Button(self, text=i, command=lambda: self.edit(i))

by

self.widgetdata[i] = Button(self, text=i, command=lambda i=i: self.edit(i))

Explanation: the body of the lambda function is executed when clicking the Button, so it uses the current value of i at execution time (i.e. the index of the last created Button), not at definition time. Creating an aliased argument, forces the creation of a local variable for each loop step, each having a different value, so refering to a different Button.

sciroccorics
  • 2,357
  • 1
  • 8
  • 21