Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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
Command 撤消绘制程序_Command_Design Patterns_Paint_Undo - Fatal编程技术网

Command 撤消绘制程序

Command 撤消绘制程序,command,design-patterns,paint,undo,Command,Design Patterns,Paint,Undo,我正在研究如何编写一个支持撤销的绘图程序,并看到,最有可能的是,命令模式就是我想要的。不过,我还是想不出什么,我希望有人能提供一个简单的答案或确认 基本上,如果我要实现撤销命令的功能,例如在屏幕上冲压一个实心圆,这是否意味着我需要将圆覆盖的帧缓冲区复制到内存中,复制到这个命令对象中?我看不到任何其他方法能够撤销可能是什么,例如,在一堆随机像素颜色上盖章 我听说一种方法就是跟踪向前的操作,当执行撤消时,您只需从步骤1开始并向前绘制到撤消之前的步骤,但是如果您要支持大型撤消堆栈,这似乎是不可行的 也

我正在研究如何编写一个支持撤销的绘图程序,并看到,最有可能的是,命令模式就是我想要的。不过,我还是想不出什么,我希望有人能提供一个简单的答案或确认

基本上,如果我要实现撤销命令的功能,例如在屏幕上冲压一个实心圆,这是否意味着我需要将圆覆盖的帧缓冲区复制到内存中,复制到这个命令对象中?我看不到任何其他方法能够撤销可能是什么,例如,在一堆随机像素颜色上盖章

我听说一种方法就是跟踪向前的操作,当执行撤消时,您只需从步骤1开始并向前绘制到撤消之前的步骤,但是如果您要支持大型撤消堆栈,这似乎是不可行的

也许解决方案介于两者之间,即每15-20个操作保留一个位图,并从最后一次“保存”开始

有人能提供一些关于这种情况下典型的公认方法的见解吗?在命令中保存缓冲区矩形,向前重做每个动作,或者我完全错过了什么

更新:大量良好的响应。谢谢大家。从我所读到的内容来看,我将通过每N个操作保存一次缓冲区来实现这一点,当用户发出一个撤销命令时,从最近保存的缓冲区中重做所有命令。我可以将N调整到尽可能高的值,这样就不会明显影响需要响应撤销的用户体验(以最大限度地减少内存使用),但我怀疑,在这一点上我还不确定,我应该能够在一个帧中执行相当多的操作,这样就不会太糟糕了。希望这种方法能让我快速确定是否转向另一个方向,而是为需要它的操作保存以前状态的位图矩形

也许解决方案介于两者之间,即每15-20个操作保留一个位图,并从最后一次“保存”开始

我会选择像这样的。无论如何,您必须在某个点绑定命令堆栈,因此如果用户清空它,您将需要一个起点


您可以变得更聪明,在到达绑定时保存缓冲区,并将其用作保存点,因为您必须从堆栈中删除命令。本质上,您的保存点缓冲区是已删除操作的表示,因此当您从撤消堆栈中删除操作时,您只需将它们写入该缓冲区。

据我所知,用于实现撤消/重做类系统的命令模式只需将操作记录在堆栈中,而不是这些操作的实际结果(因为这些将按顺序重新创建/删除)。我想你提到了这一点,但说你认为大型撤消堆栈不可行。你能更具体一点吗?我相信这是可能的。

如果你可能不会绘制巨大的位图,你的方法似乎完全可以

为了进一步简化,将整个图片写入tmp目录到磁盘上,看看用户会是什么样子


开始时不要过度设计毫无疑问,还有其他问题需要解决。

首先,要注意过度设计:如果你的应用程序不复杂,图像也不小,你可能会发现“只存储所有东西”是快速、廉价和可行的。但假设不是这样:

您是正确的,从步骤1开始,每次撤消都不可能重新绘制整个画布;除非您的绘制程序非常简单,否则某些操作可能会花费太长的时间。此外,可能不需要无限的撤消缓冲区(并且可能会非常消耗存储空间)

如果你的art程序很复杂,我实际上会从一个混合的方法开始,来处理各种各样的操作。每隔一段时间保存帧缓冲区(你建议的每隔15-20个命令似乎可以;我可能从10开始,在它工作后进行调整)但不要让“每15次操作”变得僵化,因为可能有一些额外的经验法则会让用户觉得更流畅

例如,一些耗时或棘手的反向操作总是会创建一个新的保存点:
-任何画布调整大小(裁剪等)
-任何保存。(“我刚刚保存”很可能是用户撤消返回的位置。)
-任何非常耗时的操作都应该在操作之后而不是之前创建一个新的保存点;也就是说,它应该标记下一个操作以保存要撤消的缓冲区。(为什么?如果操作需要30秒,您不希望堆栈中的每次撤消都需要额外的30秒以上。)
-相反,任何具有易于执行的数学负片或自反转(如光电负片)的操作都不需要费心保存帧缓冲区,并且不应计入下一次保存

所有这些都忽略了图层的问题;如果您的程序有图层,那么只保存更改的图层显然就足够了

当然,我的最高优先级建议是:无论使用什么方法,都应该为最近执行的操作保存帧缓冲区。“哎呀,不是这个意思”是撤消的最可能原因,因此您始终希望撤消一个步骤具有响应性。如果此缓冲区不是您保留的,则可以在下一次命令执行后丢弃此缓冲区

您还需要考虑什么构成一个原子撤消操作。(例如,一个笔画工具集是一个操作还是多个操作?两者都有优点和缺点。)

我听说一种方法就是跟踪向前的操作,当执行撤消时,您只需从步骤1开始并向前绘制到撤消之前的步骤

这不是一个很好的主意。用户通常只撤销最近的一些操作,他们希望它是f