【问题标题】:Undo button for System.Drawing?System.Drawing 的撤消按钮?
【发布时间】:2011-02-24 19:15:00
【问题描述】:

我正在制作一个图像编辑器,有点出于自己的乐趣,我想知道如何制作一个撤消按钮来撤消我所做的最后一次绘画?我想知道我会怎么做,教程或示例代码会很好,或者至少可以为我指明正确的方向。

谢谢!

【问题讨论】:

  • 你如何定义“最后”油漆?假设我通过拖动画笔画了一条线。那是“一个”油漆还是很多?如果您正在寻找可以为您执行此操作的 .NET 类,那么您可能会不走运。
  • 那将是一种油漆。我不是真的在找一门课。

标签: c# .net drawing system.drawing


【解决方案1】:

嘿,撤消实际上并不像听起来那么难。这里的神奇之处在于您应该将每个动作记录为绘制在列表或队列中的对象,f.ex,用户画一条线,因此您的记录可能看起来像开始点的 x,y 和终点的 x,y 或对象本身具有 Draw() 方法,因此撤消将执行的操作只是删除该对象。

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

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】:

    一个基本的方法是保留一个堆栈来保存你所做的每一次新的笔触。

    当您点击撤消按钮时,弹出堆栈并反转您的更改(取决于您的应用程序的具体情况,是否可以通过重新绘制背景颜色来购买?)

    【讨论】:

      【解决方案3】:

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

      命令对象对于 实施:

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

      编辑: 说明这有什么用处在将该命令应用到绘图上下文之前,将有关完成该操作的所有相关信息存储在该命令中。

      因此,每个操作都被压入堆栈,以便您可以弹出项目。

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

      例如,我将有一个正在运行的命令堆栈和一个正在运行的绘图对象堆栈。每 5 个命令我会将绘图对象的状态推送到它的堆栈上,因此当用户按下撤消时,我将获取绘图对象的顶部状态并将最新命令应用于对象保存最后一个。要撤消 10 个操作,我会返回绘图对象的 2 个状态,并且不需要对其应用任何新命令。

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

      【讨论】:

      • 每次询问有关撤消的问题时,我都会看到此链接。但它是解决方案的 1/4。其他 3/4 是如何跟踪应用程序的 状态 以及如何恢复它。 (并有效地做到这一点!)
      • @Andrey 编写软件并不容易,这就是为什么我们都有工作,创建软件模式是为了为问题提供可重复的解决方案,软件开发人员的角色是能够实现这些模式满足他们特定的业务需求。但是,我会修改我的答案以添加更多方向。
      猜你喜欢
      • 1970-01-01
      • 2016-06-22
      • 2013-05-10
      • 1970-01-01
      • 2016-09-22
      • 1970-01-01
      • 2017-07-13
      • 2021-05-05
      • 2012-01-12
      相关资源
      最近更新 更多