Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tkinter button commands with lambda in Python

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

like image 203
vap Avatar asked Apr 25 '13 20:04

vap


People also ask

Can we give two commands to a button in Tkinter?

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.

Why lambda is used in Tkinter?

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.

How do you call a function with an argument on button click in Python?

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.

Can we use lambda function in Python?

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.


2 Answers

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)
like image 67
Joel Cornett Avatar answered Oct 06 '22 10:10

Joel Cornett


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.

like image 33
Lee Daniel Crocker Avatar answered Oct 06 '22 10:10

Lee Daniel Crocker