Hello avid python users...
I was trying to create my first GUI writing a tic-tac-toe program but I ran into a problem regarding the 9 buttons on the grid. Here is part of the code that generates the buttons:
button = 0
for x in range(3):
for y in range(3):
button = Button(root, text= " ", font=("Helvetica", 20), height=3, width=6, bg="SystemButtonFace", command=lambda button=button: b_click(button))
button.grid(row = x, column = y)
The click function looks like this:
def b_click(b):
global clicked
if b["text"] == " " and clicked == True:
b["text"] = "X"
clicked = False
elif b["text"] == " " and clicked == False:
b["text"] = "O"
clicked = True
else:
messagebox.showerror("Tic Tac Toe", "Hey! That box has already been selected \nPick another box...")
My problem is that whenever I click a button on the GUI it selects and use b_click(b) on the button to the left of whichever one I originally picked...
Help would be appreciated...
Look at this script:
import tkinter as tk
from functools import partial
def b_click(button):
button.config(text="X")
root = tk.Tk()
for x in range(3):
for y in range(3):
button = tk.Button(root, text=" ")
command = partial(b_click, button)
button.config(command=command)
button.grid(row=x, column=y)
root.mainloop()
It uses functools.partial
and <tkinter.Button>.config(...)
to pass in the button to the function. From there you can do anything you like with the button.
Edit:
functools.partial
is like a labmda
but you don't need the button=button
part. It takes at least 1 argument (the function name) and the rest of the arguments/key word arguments are passed to the function when it is called.
So
x = partial(function, arg1, arg2, kwarg1="")
x(arg3)
will be the same as function(arg1, arg2, arg3, kwarg1="text")
.