Как уже упоминалось, в lambda grid_box=grid_box:
второй grid_box
ищет переменную с именем «grid_box» в текущем контексте, но его перед вы присвоили Button
grid_box
, поэтому вы получите ошибку. Даже если вы определили grid_box
, это не сработает, потому что обратный вызов Button
command
не принимает параметров.
Решение состоит в том, чтобы написать собственный подкласс Button
, который перехватывает обратный вызов команды для добавления информацию о кнопках, которую вы хотите. Удобно, что это self
инициализируемой кнопки. Когда вы назначаете метод экземпляра для обратного вызова, он знает свое собственное «я», и его можно использовать для sh всех состояний, полезных для обратных вызовов.
from tkinter import *
from tkinter import messagebox
turn = "X"
def mark_square(box):
global turn
if box.cget('text') == " ":
box['text'] = turn
else:
messagebox.showerror(title="Invalid", message="Invalid")
class ButtonWithContext(Button):
"""Specializes tkinter.Button to allow a `command` that takes
the button as a parameter"""
def __init__(self, *args, **kwargs):
try:
self._my_command = kwargs["command"]
kwargs["command"] = self.run_command
except KeyError:
self._my_command = None
super().__init__(*args, **kwargs)
def run_command(self):
if self._my_command is not None:
return self._my_command(self)
root = Tk()
root.title("Tic-Tac-Toe")
for x in range(0, 3):
for y in range(0, 3):
grid_box = ButtonWithContext(text=" ", font=("Arial", 40), padx=20,
command=mark_square)
grid_box.grid(row=x, column=y)
root.mainloop()