在最近使用的对象上调用函数?
Call function on most recently used object?
所以,我正在使用 tkinter 为 Tic Tac Toe 编写一个图形用户界面,并且我正在尝试实现一个 "Undo" 功能。
我有一个 class "Square",它是 canvas 的子 class,具有绘制零、交叉或清除自身的方法。 "Undo" 函数应该计算出最近播放的方块是哪个,并调用它的 clear 方法。
我有一个所有移动的全局列表,称为 "notation",所以如果我能够对 notation.pop() 返回的对象调用清除函数,这应该可以工作。
这是实现它的合理方式吗?我该怎么做?
下面是我的代码和我当前的 "Undo" 按钮,它被硬编码为只能撤消 C,中央广场。
import tkinter as tk
# notation is a list containing all moves made
notation = []
# This class defines a Square, just a clickable canvas which shows a nought or cross when clicked
class Square(tk.Canvas):
def __init__(self, name, master=None, width=None, height=None):
super().__init__(master, width=width, height=height)
self.bind("<Button-1>", self.tic)
self.bind("<Button-2>", self.tac)
self.free=True
self.name=name
def tic(self, event):
""""This will draw a cross on the selected Square."""
if self.free:
self.create_line(30, 30, 170, 170)
self.create_line(30, 170, 170, 30)
self.free = False
global notation
notation.append(self.name)
print(notation)
def tac(self, event):
""""This will draw a nought on the selected Square."""
if self.free:
self.create_oval(30, 30, 170, 170)
self.free = False
global notation
notation.append(self.name)
print(notation)
def clear(self):
""""This will clear the selected Square."""
if not self.free:
self.delete("all")
self.free = True
global notation
notation.pop()
print(notation)
root = tk.Tk()
root.title("Tic Tac Toe")
NW = Square("NW", master=root, width=200, height=200)
NW.grid(row=0, column=0)
N = Square("N", master=root, width=200, height=200)
N.grid(row=0, column=1)
NE = Square("NE", master=root, width=200, height=200)
NE.grid(row=0, column=2)
W = Square("W", master=root, width=200, height=200)
W.grid(row=1, column=0)
C = Square("C", master=root, width=200, height=200)
C.grid(row=1, column=1)
E = Square("E", master=root, width=200, height=200)
E.grid(row=1, column=2)
SW = Square("SW", master=root, width=200, height=200)
SW.grid(row=2, column=0)
S = Square("S", master=root, width=200, height=200)
S.grid(row=2, column=1)
SE = Square("SE", master=root, width=200, height=200)
SE.grid(row=2, column=2)
# Creating File Menu
menu = tk.Menu(root)
root.config(menu=menu)
fileMenu = tk.Menu(menu)
menu.add_cascade(label="File", menu=fileMenu)
fileMenu.add_command(label="Undo", command=lambda: C.clear())
root.mainloop()
你的想法有点对。您需要做的是将整个实例添加到符号列表中,然后当您弹出最后一个时,您可以调用它的清除方法:
def tac(self, event):
notation.append(self) # add this instance to the list
...
fileMenu.add_command(label="Undo", command=lambda: notation.pop().clear())
并去掉 clear 方法中的 pop
。
编辑:您可能知道,全局变量不好。在这种情况下,我们使用 class 变量,这些变量基本上是 class 的所有实例都可以访问的实例变量。 class 变量是在方法之外定义的,没有 "self." 前缀,但是您需要使用 class 名称或 "self" 来访问它(例如,在您的情况下从 class 内部使用 self.notaion
或从外部使用 Square.notation
访问它)。我们还将使用 class 方法来操作它们。看看你能不能理解这个:
import tkinter as tk
class Square(tk.Canvas):
notation = [] # this is a class variable
def __init__(self, name, master=None, width=None, height=None):
super().__init__(master, width=width, height=height)
self.bind("<Button-1>", self.tic)
self.bind("<Button-2>", self.tac)
self.free=True
self.name=name
def tic(self, event):
""""This will draw a cross on the selected Square."""
if self.free:
self.create_line(30, 30, 170, 170)
self.create_line(30, 170, 170, 30)
self.free = False
self.notation.append(self)
self.print()
def tac(self, event):
""""This will draw a nought on the selected Square."""
if self.free:
self.create_oval(30, 30, 170, 170)
self.free = False
self.notation.append(self)
self.print()
def clear(self):
""""This will clear the selected Square."""
if not self.free:
self.delete("all")
self.free = True
self.print()
@classmethod
def undo(cls):
cls.notation.pop().clear()
@classmethod
def print(cls):
print('History:', *[s.name for s in cls.notation])
root = tk.Tk()
root.title("Tic Tac Toe")
for i, name in enumerate('NW N NE W C E SW S SE'.split()):
s = Square(name, master=root, width=200, height=200)
row, column = divmod(i, 3)
s.grid(row=row, column=column)
# Creating File Menu
menu = tk.Menu(root)
root.config(menu=menu)
fileMenu = tk.Menu(menu)
menu.add_cascade(label="File", menu=fileMenu)
fileMenu.add_command(label="Undo", command=Square.undo)
root.mainloop()
我也去掉了你的重复。记住 DRY ... 如果您是 copy/pasting 代码,那么您正在执行计算机的工作。
所以,我正在使用 tkinter 为 Tic Tac Toe 编写一个图形用户界面,并且我正在尝试实现一个 "Undo" 功能。
我有一个 class "Square",它是 canvas 的子 class,具有绘制零、交叉或清除自身的方法。 "Undo" 函数应该计算出最近播放的方块是哪个,并调用它的 clear 方法。
我有一个所有移动的全局列表,称为 "notation",所以如果我能够对 notation.pop() 返回的对象调用清除函数,这应该可以工作。
这是实现它的合理方式吗?我该怎么做?
下面是我的代码和我当前的 "Undo" 按钮,它被硬编码为只能撤消 C,中央广场。
import tkinter as tk
# notation is a list containing all moves made
notation = []
# This class defines a Square, just a clickable canvas which shows a nought or cross when clicked
class Square(tk.Canvas):
def __init__(self, name, master=None, width=None, height=None):
super().__init__(master, width=width, height=height)
self.bind("<Button-1>", self.tic)
self.bind("<Button-2>", self.tac)
self.free=True
self.name=name
def tic(self, event):
""""This will draw a cross on the selected Square."""
if self.free:
self.create_line(30, 30, 170, 170)
self.create_line(30, 170, 170, 30)
self.free = False
global notation
notation.append(self.name)
print(notation)
def tac(self, event):
""""This will draw a nought on the selected Square."""
if self.free:
self.create_oval(30, 30, 170, 170)
self.free = False
global notation
notation.append(self.name)
print(notation)
def clear(self):
""""This will clear the selected Square."""
if not self.free:
self.delete("all")
self.free = True
global notation
notation.pop()
print(notation)
root = tk.Tk()
root.title("Tic Tac Toe")
NW = Square("NW", master=root, width=200, height=200)
NW.grid(row=0, column=0)
N = Square("N", master=root, width=200, height=200)
N.grid(row=0, column=1)
NE = Square("NE", master=root, width=200, height=200)
NE.grid(row=0, column=2)
W = Square("W", master=root, width=200, height=200)
W.grid(row=1, column=0)
C = Square("C", master=root, width=200, height=200)
C.grid(row=1, column=1)
E = Square("E", master=root, width=200, height=200)
E.grid(row=1, column=2)
SW = Square("SW", master=root, width=200, height=200)
SW.grid(row=2, column=0)
S = Square("S", master=root, width=200, height=200)
S.grid(row=2, column=1)
SE = Square("SE", master=root, width=200, height=200)
SE.grid(row=2, column=2)
# Creating File Menu
menu = tk.Menu(root)
root.config(menu=menu)
fileMenu = tk.Menu(menu)
menu.add_cascade(label="File", menu=fileMenu)
fileMenu.add_command(label="Undo", command=lambda: C.clear())
root.mainloop()
你的想法有点对。您需要做的是将整个实例添加到符号列表中,然后当您弹出最后一个时,您可以调用它的清除方法:
def tac(self, event):
notation.append(self) # add this instance to the list
...
fileMenu.add_command(label="Undo", command=lambda: notation.pop().clear())
并去掉 clear 方法中的 pop
。
编辑:您可能知道,全局变量不好。在这种情况下,我们使用 class 变量,这些变量基本上是 class 的所有实例都可以访问的实例变量。 class 变量是在方法之外定义的,没有 "self." 前缀,但是您需要使用 class 名称或 "self" 来访问它(例如,在您的情况下从 class 内部使用 self.notaion
或从外部使用 Square.notation
访问它)。我们还将使用 class 方法来操作它们。看看你能不能理解这个:
import tkinter as tk
class Square(tk.Canvas):
notation = [] # this is a class variable
def __init__(self, name, master=None, width=None, height=None):
super().__init__(master, width=width, height=height)
self.bind("<Button-1>", self.tic)
self.bind("<Button-2>", self.tac)
self.free=True
self.name=name
def tic(self, event):
""""This will draw a cross on the selected Square."""
if self.free:
self.create_line(30, 30, 170, 170)
self.create_line(30, 170, 170, 30)
self.free = False
self.notation.append(self)
self.print()
def tac(self, event):
""""This will draw a nought on the selected Square."""
if self.free:
self.create_oval(30, 30, 170, 170)
self.free = False
self.notation.append(self)
self.print()
def clear(self):
""""This will clear the selected Square."""
if not self.free:
self.delete("all")
self.free = True
self.print()
@classmethod
def undo(cls):
cls.notation.pop().clear()
@classmethod
def print(cls):
print('History:', *[s.name for s in cls.notation])
root = tk.Tk()
root.title("Tic Tac Toe")
for i, name in enumerate('NW N NE W C E SW S SE'.split()):
s = Square(name, master=root, width=200, height=200)
row, column = divmod(i, 3)
s.grid(row=row, column=column)
# Creating File Menu
menu = tk.Menu(root)
root.config(menu=menu)
fileMenu = tk.Menu(menu)
menu.add_cascade(label="File", menu=fileMenu)
fileMenu.add_command(label="Undo", command=Square.undo)
root.mainloop()
我也去掉了你的重复。记住 DRY ... 如果您是 copy/pasting 代码,那么您正在执行计算机的工作。