简体   繁体   English

在我的Python乌龟绘图程序中实现重做的最pythonic方法?

[英]Most pythonic way to implement redoing in my Python turtle drawing program?

I have created a turtle drawing program that draws any letter on the turtle canvas that the user presses on the keyboard. 我创建了一个乌龟绘图程序,该程序可以在用户按下键盘上的乌龟画布上绘制任何字母。 I have already implemented an undo function to undo the last drawing the user calls ( shown below ), but now I am looking at how to implement a redo function. 我已经实现了撤消功能来撤消用户调用的最后一个图形( 如下所示 ),但是现在我正在研究如何实现重做功能。 Can anybody give me any tips or tricks on the most pythonic way to do this, possibly based on my current undo function? 有人可以根据我目前的撤消功能,以最pythonic的方式给我任何提示或技巧吗? I have googled a lot about this to no avail, so any help regarding this issue is much appreciated. 我已经对此进行了大量搜索,但都无济于事,因此,非常感谢您对此问题的任何帮助。

My undo function: 我的撤消功能:

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

EDIT: Just to avoid confusion, what I want the "redo" to do is to clear the canvas, then redraw everything with one function past the undone point each time a button calling "redo" is pressed. 编辑:为避免混淆,我要“重做”的工作是清除画布,然后每按下一个调用“重做”的按钮,就用一个功能重绘过去撤消点之后的所有内容。 For example, if the user draws "HELLO" on the canvas, and the user undoes up until the letter "H", when redo is pressed once, the turtle should redraw "H(new letter user chose)L", if redo is called a second time, the turtle should draw "H(new letter user chose)LL", so on so forth. 例如,如果用户在画布上绘制“ HELLO”,并且用户撤消直到字母“ H”,则按一次重做后,乌龟应重绘“ H(用户选择的新字母)L”,如果重做为再次调用时,乌龟应绘制“ H(新字母用户选择)LL”,依此类推。 It should also be able to change the undone letter to a letter the user replaced it with (hence the "redo"). 它还应该能够将撤消的字母更改为用户用其替换的字母(因此为“重做”)。 For example, if the user undoes up to, for example, "H" in "HELLO", and the user replaces "E" with "A", then when redo is called, it should draw "HAL". 例如,如果用户撤消了例如“ HELLO”中的“ H”,并且用户将“ E”替换为“ A”,则在调用重做时,应绘制“ HAL”。

A simple method to handle undo/redo is to use two stacks. 处理撤消/重做的一种简单方法是使用两个堆栈。

If you think of it like a web browser, One stack is for going backwards and the other stack is for going forwards . 如果您将其视为网络浏览器,则一个堆栈用于backwards ,另一个堆栈用于forwards

New Action with Overwrite: Each new user action is done, then pushed onto the backwards stack. 带有覆盖的新操作:完成每个新的用户操作,然后将其推入backwards堆栈。 Finally, the next redo action is overwritten by having an action popped and discarded from the forwards stack (if it is not empty). 最后,通过弹出一个动作并将其从forwards堆栈中丢弃(如果它不为空),下一个重做动作将被覆盖。

Undo: When the user wants to go backwards ( undo ), an action is popped from the backwards stack, the action is undone, then the action is pushed to the forwards stack. 撤消:当用户想向后退( undo )时,将从backwards堆栈中弹出一个动作,撤消该动作,然后将该动作推入forwards堆栈。

Redo All: When the user wants to go forwards ( redo ), an action is popped from the forwards stack, the action is redone, then the action is pushed to the backwards stack. 全部重做:当用户要前进( redo )时,将从forwards堆栈中弹出一个动作,重做该动作,然后将该动作推入backwards堆栈。 In this case, redo is actually redo all , so redo should be repeated until the forwards stack is empty. 在这种情况下, redo实际上是redo all ,所以redo应重复,直到forwards堆栈是空的。

Warning: Ensure that each action is defined such that it is self-contained, otherwise you may run into issues when actions are overwritten. 警告:请确保每个动作的定义都是独立的,否则覆盖动作时可能会遇到问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM