-1

I created button dynamically and i want to give them a command to change their picture and change position. Now is the problem that i dont manage to pass the button himself in command

I exchanged the pictures in the code below with text but the problem is still the same.

It doesn't work with lambda or i haven't used it right.

from tkinter import *

karten = {'Stapel': [['D','A','BDA','D'],['D','2','BD2','D']]}
def p(button):
    button.config(text='HI')
RS = 'RS'
DA = 'DA'
D2 = 'D2'
root = Tk()
for i in karten:
    for j in karten[i]:
        vars()[j[2]] = Button(root,text=vars()[j[0]+j[1]],command=lambda: p(vars()[j[2]]))
        vars()[j[2]].pack()
root.mainloop()

i expected that the button changes the text but it only produced an error.

MrAntobr
  • 3
  • 1

1 Answers1

2

The dict returned by vars is different inside the lambda and outside of it, thus you put your key in one dict, then try to retrieve it from another. Also, you should probably not use vars (or globals or locals) in the first place, if you can help it. (And for the text, using vars() does not make any sense whatsoever.)

Instead, you could just create a dedicated dictionary for the buttons in the global scope and access that one in your lambda. The values does not have to be present in the dict when you create the lambda, just when you call it.

buttons = {}
for i in karten:
    for j in karten[i]:
        b = Button(root, text=j[0]+j[1], command=lambda j=j: p(buttons[j[2]]))
        b.pack()
        buttons[j[2]] = b

Also note the j=j in the lambda (see here for more explanation).

Alternatively, you could use configure to set the command after creating the button and defining the variable, thus not needing the dictionary at all:

for i in karten:
    for j in karten[i]:
        b = Button(root, text=j[0]+j[1])
        b.configure(command=lambda b=b: p(b))
        b.pack()

Or using functools.partial instead of lambda b=b:

        b.configure(command=functools.partial(p, b))
tobias_k
  • 81,265
  • 12
  • 120
  • 179