I am trying to create buttons in tkinter within a for
loop. And with each loop pass the i
count value out as an argument in the command value. So when the function is called from the command
value I can tell which button was pressed and act accordingly.
The problem is, say the length is 3, it will create 3 buttons with titles Game 1 through Game 3 but when any of the buttons are pressed the printed value is always 2
, the last iteration. So it appears the buttons are being made as separate entities, but the i
value in the command arguments seem to be all the same. Here is the code:
def createGameURLs(self): self.button = [] for i in range(3): self.button.append(Button(self, text='Game '+str(i+1), command=lambda: self.open_this(i))) self.button[i].grid(column=4, row=i+1, sticky=W) def open_this(self, myNum): print(myNum)
Is there a way to get the current i
value, each iteration, to stick with that particular button?
The Tkinter button has only one command property so that multiple commands or functions should be wrapped to one function that is bound to this command .
Change your lambda to lambda i=i: self.open_this(i)
.
This may look magical, but here's what's happening. When you use that lambda to define your function, the open_this call doesn't get the value of the variable i at the time you define the function. Instead, it makes a closure, which is sort of like a note to itself saying "I should look for what the value of the variable i is at the time that I am called". Of course, the function is called after the loop is over, so at that time i will always be equal to the last value from the loop.
Using the i=i
trick causes your function to store the current value of i at the time your lambda is defined, instead of waiting to look up the value of i later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With