ive tried searching for a solution but couldn't find one that works. I have a 2d list of tkinter Buttons, and i want to change their Text when it is clicked by the mouse. I tried doing this:
def create_board(number):
print(number)
for i in range (0,number):
buttonList.append([])
for j in range(0,number):
print(i,j)
buttonList[i].append(Button(root, text = " ", command = lambda: update_binary_text(i,j)))
buttonList[i][j].pack()
Then when it is clicked it calls this function:
def update_binary_text(first,second):
print(first,second)
buttonList[first][second]["text"] = "1"
When i click a button, it simply does nothing, i had the program display the indexes of the button that was clicked, and they ALL show 4, 4 (this is when the variable number=5) Is there an solution to this?
this is my first python attempt for a class.
Thanks
We can perform a certain action with the help of a Button that encapsulates the function and the objects. However, there might be cases when we want to perform multiple operations with a single button. This can be achieved by defining the lambda functions which target multiple events or callback in the application.
Python lambda function can be used in GUI programming with Tkinter. It allows to create small, inline functions for the command parameter. We have three buttons that share one callback. The lambda function allows us to send specific data to the callback function.
Import the Tkinter package and create a root window. Give the root window a title(using title()) and dimension(using geometry()), now Create a button using (Button()). Use mainloop() to call the endless loop of the window. lambda function creates a temporary simple function to be called when the Button is clicked.
Python Lambda Functions are anonymous function means that the function is without a name. As we already know that the def keyword is used to define a normal function in Python. Similarly, the lambda keyword is used to define an anonymous function in Python.
You can fix this problem by creating a closure for i
and j
with the creation of each lambda:
command = lambda i=i, j=j: update_binary_text(i, j)
You could also create a callback factory with references to the button objects themselves:
def callback_factory(button):
return lambda: button["text"] = "1"
And then in your initialization code:
for j in range(0, number):
new_button = Button(root, text=" ")
new_button.configure(command=callback_factory(new_button))
new_button.pack()
buttonList.append(new_button)
Whenever I need a collection of similar widgets, I find it's simplest to enclose them in an object and pass a bound-method as callback rather than playing tricks with lambda. So, instead of having a list like buttonList[]
with widgets, create an object:
class MyButton(object):
def __init__(self, i, j):
self.i = i
self.j = j
self.button = Button(..., command = self.callback)
def callback(self):
. . .
Now, you have a list buttonList[]
of these objects, rather than the widgets themselves. To update the text, either provide a method for that, or else access the member directly: buttonList[i].button.configure(. . .)
And when the callback is activated, it has the entire object and whatever attributes you might need in self
.
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