在最近使用的对象上调用函数?

时间:2017-06-20 22:13:31

标签: python tkinter menu undo

所以,我正在使用tkinter为Tic Tac Toe写一个gui,而我正试图实现一个" Undo"特征

我有一个班级" Square"它是canvas的子类,具有绘制零,交叉或清除自身的方法。 "撤消"函数应该计算出最近播放的正方形,并在其上调用clear方法。

我有一个所有动作的全局列表,名为" notation",所以如果我能够在notation.pop()返回的对象上调用clear函数,这应该可以。

这是实现这个的合理方式,我该怎么做?

以下是我的代码,以及我当前的"撤消"按钮,硬编码只能撤消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()

1 个答案:

答案 0 :(得分:1)

你有一个正确的想法。您需要做的是将整个实例添加到符号列表中,然后当您弹出最后一个实例时,您可以将其称为明确的方法:

def tac(self, event):
        notation.append(self) # add this instance to the list

...
fileMenu.add_command(label="Undo", command=lambda: notation.pop().clear())

在清除方法中摆脱pop

编辑:您可能知道,全局变量很糟糕。在这种情况下,我们使用类变量,它们基本上是可由类的所有实例访问的实例变量。类变量是在方法之外定义的,没有&#34; self。&#34;前缀,但是你需要使用类名或&#34; self&#34;访问它(例如,在您的情况下,您可以从课程内部使用self.notaion或从外部Square.notation访问它)。我们还将使用类方法来操作它们。看看你是否能理解这一点:

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()

我也摆脱了你的重复。记住干......如果你是复制/粘贴代码,那么你正在做计算机的工作。