Undo button for System.Drawing?

2020-03-26 06:39发布

问题:

I am making a image editor kinda for own enjoyment and was wondering how could I make a undo button to undo the last paints I did? I want to know how I would about this, a tutorial or sample code would be nice or at least something pointing me in the right direction.

Thanks!

回答1:

heh undo in really non that hard as it sounds. The magic here that you should record each action as object which is painted in a list or queue, f.ex, user draws a line, so your record could look like x,y of start poing, and x,y of end point or object it self which have method Draw(), so what undo will do just remove that object.

in code that could look something like this:

interface IDrawObject
{
     public void Draw();
}

class Line : IDrawObject
{
    private Point _startP;
    private Point _endP;

    public Line(Point startPoint; Poing endPoint)
    {
        _startP = startPoint;
        _endP = endPoint;
    }

    public void Draw()
    {
        //* call some generic draw processor to perform the action with your given parameters.
    }
}

class Rectangle : IDrawObject
{
    //* your code.
    public void Draw()
    {
         //* call some generic draw processor to perform the action with your given parameters.
    }
}

//* then in your code, you could have something like this.
List<IDrawObject> myObjectsINeedToDraw = new List<IDrawObject>();
myObjectsINeedToDraw.Add(new Line(new Point(0, 0), new Point(10, 10));

foreach(IDrawObject objectToDraw in myObjectsINeedToDraw)
{
    //* will draw your object.
    objectToDraw.Draw();
}

//* in this way you will have unlimited history of your objects, and you will always can remove object from that list.


回答2:

One basic method is to keep a Stack that will hold every new brushstroke you make.

As you hit the undo button, pop off the stack and reverse your change (Depends on the specifics of your app, buy maybe by repainting in the background color?)



回答3:

http://en.wikipedia.org/wiki/Command_pattern

Command objects are useful for implementing:

Multi-level undo If all user actions in a program are implemented as command objects, the program can keep a stack of the most recently executed commands. When the user wants to undo a command, the program simply pops the most recent command object and executes its undo() method.

Edit: To put in perspective how this could be useful If I was going to solve this what I would do is record each "action" the user does like draw a line etc as a command and store all the assocatied information about completing that action inside that command before applying it to the drawing context.

So every action is pushed onto a stack so you can then pop back off items.

To facilitate speed I would also probably look at something like recording the state of the drawing object for a series of actions. Since it's the context of drawing it would probably be easier to start from a known drawing state and reapply commands to create the current version.

So as an example I would have a running stack of commands and a running stack of drawing objects. Every 5 commands I would push the state of the drawing object onto it's stack, so then when a user would press undo, I would grab the top state of the drawing object and apply the newest commands to the object save for the last one. To undo 10 actions, I would go back 2 states of drawing objects and not need to apply any new commands to it.

You will most likely want to limit the depth of undo/redo states you can do in your program otherwise it will infinitely grow in memory.