-1

i want to create multiple buttons in Tkinter, in a for loop. The problem is that I'm iterating through a dataframe (the values in the rows are the content of the Tkinter gadets I'm creating) with .iterrows which means, I have no "i", only rows and index.

The problem is, that as I'm creating the buttons and give them different commands with lambda i:i=SomeFunction(somevariable), and here I have to use a variable other than "i". The result is that the commands are all referring at the end for to the last value of this "somevariable" and not to the value of it as it was at the creation of the button.

import tkinter

def printout(somevariable):
    print(somevariable)

window = tkinter.Tk()

i = 0
somevariable = 0
for index, rows in enumerate(["a","b","c","d"]):
    b = tkinter.Button(window,  
                       text=rows, 
                       command= lambda i=i: printout(somevariable))
    b.pack()
    somevariable = somevariable + 1

window.mainloop()

And all the buttons are containing as command the very last value of the "somevariable".

Any idea how to make this work??

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
Mark
  • 83
  • 1
  • 1
  • 7

2 Answers2

0

Disclaimer: this answer is "older" as Naes one, because I tried to solve it - but did not until Nae posted the dupe. To explain what happens further:

The problem is, that your lambda is evaluated when you press the button. It will print the value of somevariable at this time. You can fix the current value of somevariable by providing your lambda with a snapshot of somevariable on creation of the lambda by using Nae' answer - to make this more clear I would reformulate it as:

command= lambda s=somevariable: printout(s)) 

to make it clear that the lambda uses s which takes the value of somevariable at this time and when called, will print s.

Full example:

import tkinter 

def printout(somevariable):
    print(somevariable)

window = tkinter.Tk()    

somevariable = 0
for index, rows in enumerate(["a","b","c","d"]): 
    b = tkinter.Button(window,  
                       text=rows, 
                       command= lambda s=somevariable: printout(s)) 
    b.pack()
    somevariable = somevariable + 1

window.mainloop()

pressed buttons 1-4 in row

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • Thanks a lot, it's working. It saved me hours of trying and actually the missing key for a waaaaay bigger project. Thanks again. – Mark Mar 03 '18 at 10:48
  • @Mark Nae solved it / found the dupe. I merely poached and explained why it works if you do it that way. – Patrick Artner Mar 03 '18 at 10:55
0

Replace:

command= lambda i=i: printout(somevariable))

with:

command= lambda somevariable=somevariable: printout(somevariable))
Nae
  • 14,209
  • 7
  • 52
  • 79