Frage

I am currently trying to create an undo function for a paint program I am creating in python and pygame. I have decided that I am going to copy the canvas after each change made to it by the user and add that copy to a list. If the user presses on the undo button, the previous image will be loaded onto the canvas. Is the append function applicable to this situation (I have it in the code down below)? I am just wondering how this can be completed. Is this an efficient method or is there a better way to do this?

I also am also wondering if the placement of the "canvasFrame = canvas.copy()" is correctly placed here (this is my brush tool. Is the canvas.copy() supposed to be placed after all of my calculations?):

if mb[0] == 1  and canvas.collidepoint(mx,my):
    screen.set_clip(canvas)
    canvasFrame = canvas.copy()
    frames.append(canvasFrame)
    if tool == "brush":
        x=mx-omx
        y=my-omy
        d = int(((x)**2+(y)**2)**0.5)
        if d == 0:
            d = 1
        for i in range(int(d)):
            dx = int(omx+i/d*x)
            dy = int(omy+i/d*y)
            draw.circle(screen,(c),(dx,dy),sz)
    screen.set_clip(None)

Basically, what I would like to know is how I would set a maximum amount of copies in the list (I assume by using the function MAX but I am not exactly sure how to use it for lists) and also how I would load previous canvas images onto the canvas. I have spent quite a bit of time searching for information regarding this problem but have been unsuccessful so far. Any help is appreciated. Thank You.

I am fairly new to python and do not have much experience with the more advanced functions that can be used in python so if this method may sound unnecessarily complicated it is probably due to the fact that I do not have many functions that I can work with.

War es hilfreich?

Lösung

Personally I wouldn't go with saving a copy of the entire canvas, I would store the event such as appending somthing like this to a log history.append( 4, 2, (128, 128, 128) the 4,2 would be the X/Y co-ords at where the user was painting/changeing the color of the tile/pixel, the (128, 128, 128) would be the old color that tile was. So when you use the undo function you will want to make the program go to the last item in the list history[len(history)-1] and replace the color at X/Y to (128, 128, 128) (history[len(history)-1][2])

Like this

BLACK = (0, 0, 0)

current_color = None #global

history = [] #global

...

def draw(event):
    global history, canvas
    #when a tile gets painted on
    X=event.pos[0]
    Y=event.pos[1]
    history.append(X,Y,canvas[X][Y])
    canvas[X][Y] = current_color



def undo():
    global history, canvas
    X = history[len(history)-1][0]
    Y = history[len(history)-1][1]
    color = history[len(history)-1][2]

    canvas[X][Y] = color
    history.pop(len(history)-1)

This way you are using a lot less ram, so you can store a lot more events.

Andere Tipps

If you plan to have a maximum number of history entries, I would go for collections.deque instead of a list.

Using a deque, you can specify the maximum number of entries. If entries is appended to one end of the list and the deque is full, a corresponding number of entries is removed from the opposite end.

from collections import deque

max_steps = 3
history = deque([1, 2, 3], maxlen=max_steps)
print history # deque([1, 2, 3], maxlen=3)
history.append(4)
print history # deque([2, 3, 4], maxlen=3)
history.extend([5, 6])
print history # deque([4, 5, 6], maxlen=3)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top