在我的Python龟绘图程序中实现重做的大多数pythonic方法?

时间:2016-01-07 01:38:15

标签: python python-3.x turtle-graphics undo-redo redo

我创建了一个乌龟绘图程序,可以在用户在键盘上按下的乌龟画布上绘制任何字母。我已经实现了撤消功能来撤消用户调用的最后一个绘图(如下所示),但现在我正在研究如何实现重做功能。任何人都可以根据我目前的撤销功能,以最强 pythonic 的方式给我任何提示或技巧吗?我搜索了很多关于此的内容无济于事,所以对此问题的任何帮助都非常感谢。

我的撤消功能:

def Clear():
    clear()
    speed(0)
    tracer(0,0)



def undoHandler():
    if len(function) > 0:
        undoHandler.handling = True
        if not hasattr(undoHandler, "counter"):
            undoHandler.counter = 0
        undoHandler.counter += 1
        Clear()
        function.pop()
        penup()
        try:
            goto(o,p)
            print("Gone to")
        except:
            goto(-200, 100)
        pendown()

        # "function" is a deque I created with the letter functions appended to it        
        # Items created based on a Points class that also stores all the attributes including the width, height, color, etc. of each letter.     
        # Items from a queue I created for the letter functions. The following executes each item from the deque.
        try:
            for i in function:
            k = i.getXY()
            penup()
            goto(k)
            pendown()
            hk = i.getletterheight()
            global letter_height
            letter_height = hk
            rk = i.getletterwidth()
            global letter_width
            letter_width = rk
            hw = i.getwidth()
            width(hw)
            op = i.getcolor()
            try:
                color(op)
            except:
                for g in colors:
                cp = g.getcolor2()
                colormode(255)
                color(cp)
           j = i.getfunction()
           j()
        except:
            pass



   update()

编辑:为了避免混淆,我希望“重做”做的是清除画布,然后每次按下一个按钮调用“重做”时,用一个函数重绘所有内容。被压了。例如,如果用户在画布上绘制“HELLO”,并且用户撤消直至字母“H”,则当按下一次重做时,乌龟应该重绘“H(新字母用户选择)L”,如果重做是第二次叫,乌龟应画“H(新信用户选择)LL”,依此类推。它还应该能够将撤消的字母更改为用户替换它的字母(因此“重做”)。例如,如果用户撤消例如“HELLO”中的“H”,并且用户将“E”替换为“A”,那么当调用重做时,它应该绘制“HAL”。

1 个答案:

答案 0 :(得分:2)

处理撤消/重做的一种简单方法是使用两个堆栈。

如果您将其视为Web浏览器,则一个堆栈用于转发backwards而另一个堆栈用于转发forwards

覆盖新操作:每个新用户操作都已完成,然后推送到backwards堆栈。最后,通过弹出一个动作并从forwards堆栈中丢弃(如果它不为空)来覆盖下一个重做动作。

撤消:当用户想要倒退(undo)时,会从backwards堆栈弹出一个操作,撤消操作,然后推送操作到forwards堆栈。

全部重做:当用户想要前进(redo)时,会从forwards堆栈弹出一个操作,重做操作,然后操作是推到backwards堆栈。在这种情况下,redo实际上是redo all,因此redo应该重复,直到forwards堆栈为空。

警告:确保定义每个操作以使其自包含,否则在覆盖操作时可能会遇到问题。