Tkinter Creating Buttons in For Loop Passing Command Arguments

tkinter button different command for loop in dictionary not working

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.

Tkinter assign button command in a for loop with lambda

The problem is your lambda expression in the for loop. It is using the name variable, but the name variable gets reassigned each iteration of the for loop, so in the end, all of the buttons get the last value that name was assigned to in the for loop. To avoid this you can use default keyword parameters in your lambda expression like so:

user_button = Tkinter.Button(self.root, text=name,
command=lambda name=name: self.a(name))

This binds the current value of the name variable to the lambda's name keyword argument each time through the loop, producing the desired effect.

Pass button text to command as arg with tkinter button

You can use default value of argument on the lambda:

for folder in os.listdir("Servers"):
btns.append(
tk.Button(
master,
text=folder,
command=lambda f=folder: handleButton(f)
)
)

Creating Tkinter buttons in a loop and setting the command for each button to take in the indices of the loop

You need to create a local variable in lambda when using a loop

button = Button(root, text="0", height=2, width=10, command=lambda x_p=i,y_p=j: self.if_clicked_square(x_p,y_p))
button.place(x=25 + (100 * j), y=100 + (100 * i))

tkinter Button command doesn't work properly in iteration

This is a tricky little corner of Python. Remember that your lambda function isn't evaluated until the lambda is actually executed. By the time the lambda is executed, a has the value 2, for all three callbacks. What you need to do is "capture" the loop value, by passing it as a default parameter to the function:

    dict2[a]= Button(root,text='clear',command=lambda a=a :list1[a].set('')).place(relx=0.86,rely=0.32+label_rely)

Declare buttons in a loop in Tkinter (Python3)

Here is a very simple example on how to do so, by making a list of all the 25 color and then using the conventional matrix looping and assigning items to the buttons, like:

from tkinter import *

root = Tk()

colors = ['Red','Orange','Yellow','Green','Blue','Purple','Brown','Magenta',
'Tan','Cyan','Olive','Maroon','Navy','Aquamarine','Turquoise','Silver',
'Lime','Teal','Indigo','Violet','Pink','Black','White','Gray','crimson']
colors = list(reversed(colors)) # Reversing list bc pop returns last item

def color_changer(btn,color):
btn.config(fg=color) # Change the color of the corresponding button

for i in range(5): # Number of rows
for j in range(5): # Number of column
color = colors.pop() # First color
btn = Button(root,text=color,fg='black',width=25)
btn.grid(row=i,column=j) # Place the widget
btn['command'] = lambda btn=btn,color=color: color_changer(btn,color) # Assign a command

root.mainloop()

There is a caveat here, you should define exactly 25 colors, else, you should use try to catch the IndexError that comes up and ignore it.

How does the function work?:
You are using lambda to create a new nameless function that takes in btn and color and passes that btn and color to the color_changer(). This way we can store corresponding btn and color, unlike if you would normally assign it like lambda: color_changer(btn,color), it is just going to pass the last popped item. This is usually how we assign commands for buttons inside a loop.

Alternative(to lambda):
You can also use a nested function(avoiding lambdas). So the function would be like:

def nester(btn,color):
def color_changer():
btn.config(fg=color)
return color_changer

and the command would be like:

btn['command'] = nester(btn,color)

This is similar to what functools.partial does.



Related Topics



Leave a reply



Submit