Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 撤消系统绘图的按钮?_C#_.net_Drawing_System.drawing - Fatal编程技术网

C# 撤消系统绘图的按钮?

C# 撤消系统绘图的按钮?,c#,.net,drawing,system.drawing,C#,.net,Drawing,System.drawing,我制作一个图像编辑器是为了自娱自乐,我想知道如何制作一个撤销按钮来撤销我上次画的画?我想知道我会怎么做,一个教程或示例代码会很好,或者至少能为我指明正确的方向 谢谢 命令对象对于 实施: 多级撤消 如果程序中的所有用户操作都作为命令对象实现, 该程序可以保存 最近执行的命令。什么时候 如果用户希望撤消命令,则 程序只是弹出最新的 命令对象并执行其undo() 方法 编辑:如果我要解决这个问题,这将是多么有用。我要做的是将用户喜欢的每一个“动作”记录为一个命令,并在将其应用到绘图上下文之前,将有

我制作一个图像编辑器是为了自娱自乐,我想知道如何制作一个撤销按钮来撤销我上次画的画?我想知道我会怎么做,一个教程或示例代码会很好,或者至少能为我指明正确的方向

谢谢

命令对象对于 实施:

多级撤消 如果程序中的所有用户操作都作为命令对象实现, 该程序可以保存 最近执行的命令。什么时候 如果用户希望撤消命令,则 程序只是弹出最新的 命令对象并执行其undo() 方法

编辑:如果我要解决这个问题,这将是多么有用。我要做的是将用户喜欢的每一个“动作”记录为一个命令,并在将其应用到绘图上下文之前,将有关完成该动作的所有关联信息存储在该命令中

所以每个动作都会被推到一个堆栈上,这样你就可以从项目中弹出

为了提高速度,我可能还会考虑记录一系列动作的绘图对象状态。因为它是绘图的上下文,所以从已知的绘图状态开始并重新应用命令来创建当前版本可能会更容易

因此,作为一个例子,我将有一个运行的命令堆栈和一个运行的图形对象堆栈。每隔5个命令,我就会将图形对象的状态推送到它的堆栈上,这样当用户按下“撤消”时,我就会抓取图形对象的顶部状态,并将最新的命令应用到对象上,保存最后一个命令。要撤消10个操作,我将返回图形对象的2个状态,并且不需要对其应用任何新命令


您很可能希望限制在程序中可以执行的撤消/重做状态的深度,否则它将在内存中无限增长。

一个基本方法是保留一个堆栈,以容纳您所做的每一笔新笔画


当你点击撤销按钮时,从堆栈中弹出并反转你的更改(取决于你的应用程序的具体情况,也许可以通过重新绘制背景色来购买?

嘿,撤销真的没有听起来那么难。这里的神奇之处在于,您应该将每个动作记录为绘制在列表或队列中的对象,f.ex,用户绘制一条线,这样您的记录可能看起来像x,y的起点,以及x,y的端点或对象本身,它们具有方法Draw(),所以undo只需删除该对象即可

在代码中,可能看起来像这样:

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.
接口IDrawObject
{
公众提款();
}
类行:IDrawObject
{
私人点(startP);;
专用点(endP);
公共线(点起点;点终点)
{
_startP=startPoint;
_endP=终点;
}
公众抽签()
{
//*调用一些通用绘图处理器以使用给定参数执行操作。
}
}
类矩形:IDrawObject
{
//*你的密码。
公众抽签()
{
//*调用一些通用绘图处理器以使用给定参数执行操作。
}
}
//*然后在你的代码中,你可以有这样的东西。
List myObjectsINeedToDraw=新列表();
添加(新行(新点(0,0),新点(10,10));
foreach(MyObject SineedToDraw中的IDrawObject对象ToDraw)
{
//*将绘制您的对象。
objectToDraw.Draw();
}
//*通过这种方式,您将拥有对象的无限历史记录,并且始终可以从该列表中删除对象。

您如何定义“最后一次”绘制?假设我通过拖动画笔画一条线。这是“一次”绘制还是“多次”绘制?如果您正在寻找一个能为您完成此操作的.NET类,您可能会运气不佳。这将是一次绘制。我并不是真的在寻找一个类。每次询问有关撤消的问题时,我都会看到此链接。但这是解决方案的1/4。其他3/4是如何跟踪应用程序的状态以及如何恢复它。(并高效地执行!)@Andrey编写软件并不容易这就是为什么我们都有工作,创建软件模式是为了为一个问题提供一个可重复的解决方案。能够实现模式以满足其特定业务需求是软件开发人员的职责。不过,我将修改我的回答,添加更多的方向。