Home > Enterprise >  Tkinter pass a button as argument
Tkinter pass a button as argument

Time:11-06

I'm new to Tkinter and as my first project I wanted to create a Tic Tac Toe. I want to create 9 buttons, that will change their background image when I click on them, the problem is that I dont want to create a function for every single button but one function that will take the button in argument and will change its background image.

The code I wrote:


def play(bid):
    if player == "X":
        bid.config(image=cross)
    if player == "O":
        bid.config(image=circle)

b1 = tk.Button(app, text="", image=white, command=lambda id=b1: play(id))
b1.grid(column=0, row=0)

How can I pass b1 as an argument to play() function? Thanks

I tried to use b1 as an argument to play(), and use play() to change b1's image. When I try to run this code I get "name b1 is not defined".

CodePudding user response:

Define a single function to create, configure, and bind your button; then your callback can close over the necessary variable referring to your button. Something like

def play(bid):
    if player == "X":
        bid.config(image=cross)
    if player == "O":
        bid.config(image=circle)

def add_button(app, r, c):
    b = tk.Button(app, text="", image=white)
    b.config(command=lambda: play(b))
    b.grid(column=c, row=r)
    return b

for row in [0,1,2]:
    for col in [0,1,2]:
        # Save the return value somewhere if necessary
        addButton(app, row, col)

The lambda expression contains a free variable b, which refers to the variable b in the closest enclosing scope, which is the call to add_button where the lambda expression is evaluated.

CodePudding user response:

One way you can do it is to separate the creation of the button from the assignment using the .config method.

b1 = tk.Button(app, text="", image=white)
b1.config(command=lambda btn_id=b1: play(btn_id))

This is not really the best way to go about it, it's better to instead pass something that defines the button like an Enum or text.

b1 = tk.Button(app, text="", image=white, command=lambda : play("b1"))

then check that "b1" is the input in your function, this way b1 can be redefined as what would happen in loops.

  • Related