Java 如何设计撤销&;在文本编辑器中重做?
我的项目的一部分是编写一个文本编辑器,用于键入一些规则、编译应用程序并运行它。编写编译器已结束并发布测试版。在最终版本中,我们必须向文本编辑器添加撤消和重做。我使用一个文件,并定期将其保存到文本编辑器中。如何设计对我的文本编辑器的撤消和重做?文件的持久化结构发生了什么变化?您可以通过两种方式进行更改:Java 如何设计撤销&;在文本编辑器中重做?,java,text-editor,undo,undo-redo,redo,Java,Text Editor,Undo,Undo Redo,Redo,我的项目的一部分是编写一个文本编辑器,用于键入一些规则、编译应用程序并运行它。编写编译器已结束并发布测试版。在最终版本中,我们必须向文本编辑器添加撤消和重做。我使用一个文件,并定期将其保存到文本编辑器中。如何设计对我的文本编辑器的撤消和重做?文件的持久化结构发生了什么变化?您可以通过两种方式进行更改: 在列表中保留编辑器状态列表和指针;撤消将指针向后移动并恢复状态,重做则向前移动,执行某些操作会丢弃指针之外的所有内容,并将状态作为新的顶部元素插入 不要保留状态,而是保留动作,这要求你对每一个动
- 在列表中保留编辑器状态列表和指针;撤消将指针向后移动并恢复状态,重做则向前移动,执行某些操作会丢弃指针之外的所有内容,并将状态作为新的顶部元素插入李>
- 不要保留状态,而是保留动作,这要求你对每一个动作都有一个抵消,以消除该动作的影响
- 动作片段:它们是更大动作的一部分,不能单独撤消或重做 (例如,移动鼠标)
- 动作:一个或多个动作片段,形成有意义的更改,可以撤消或重做, 但在磁盘上更改后,这些内容不会反映在已编辑的文档中 (例如,选择元素)
- 文档更改:一个或多个操作,用于更改编辑后的文档,使其保存到磁盘 (例如,更改、添加或删除元素)
- 文档保存:文档的当前状态被显式保存到磁盘-此时,我的编辑器丢弃了撤消历史记录,因此您无法撤消保存后的操作
- “命令”设计模式
- 仅在不可变对象上使用OO,其中所有内容都是由不可变对象构成的不可变对象,而这些对象本身又是由不可变对象构成的(这不太常见,但如果操作正确,则非常优雅)
读一本书。就我所记得的,有一个很好的例子。这是我的一份工作。哇,真是个巧合-我在最后一个小时在我的WYSIWYG文本编辑器中实现了撤销/重做: 其基本思想是将文本编辑器的全部内容保存在一个数组中,或者保存上一次编辑之间的差异 在有效点更新此数组,即每隔几个字符更新一次(检查每个按键的内容长度,如果其差异超过20个字符,则创建一个保存点)。此外,在样式设置(如果是富文本)、添加图像(如果允许)、粘贴文本等方面也会发生变化。您还需要一个指针(只是一个int变量)来指向数组中的哪个项是编辑器的当前状态) 使数组具有设置的长度。每次添加保存点时,将其添加到数组的开头,并将所有其他数据点向下移动一个。(当您有这么多保存点时,阵列中的最后一项将被遗忘) 当用户按下“撤消”按钮时,检查编辑器的当前内容是否与最新保存的内容相同(如果不相同,则说明用户自上次保存点以来进行了更改,因此保存编辑器的当前内容(以便可以重做),使编辑器等于上次保存点,并使指针变量=1(数组中的第二项)。如果它们相同,则自上次保存点以来未进行任何更改,因此您需要撤消到该点之前的点。为此,请将指针值+1递增,并使编辑器的内容=指针的值 要重做,只需将指针值减少1并加载数组的内容(确保检查是否已到达数组的末尾) 如果用户在撤消后进行编辑,则将定点值数组单元格向上移动到单元格0,并将其余单元格向上移动相同的量(一旦他们进行了不同的编辑,您不希望重做其他内容) 另一个主要要点是,确保仅在文本编辑器的内容实际发生更改时才添加保存点(否则会得到重复的保存点,并且看起来撤消对用户没有任何作用) 我无法帮助您了解java细节,但我很乐意回答您提出的任何其他问题
Nico您可以将您的操作建模为两个堆栈。一个用于撤消,另一个用于重做。您可以使用命令创建更多高级命令,例如,当您要撤消宏的操作时;或者如果您要在一个操作中对单个单词或短语的单个击键进行分组 编辑器中的每个操作(或重做操作)都会生成一个新的进入撤消堆栈的撤消命令(并清除重做堆栈)。每个撤消操作都会生成进入重做堆栈的相应重做命令
您还可以,如注释中所述,将undo和redo命令组合成一种命令类型,该命令知道如何撤消和重做其操作。基本上有两种好方法:
附言:在不可变对象上执行OO也惊人地简化了并发编程。这里有一个片段,展示了SWT如何支持撤消/重做操作。以它为例(或者直接使用它,如果编辑器基于SWT):
如果您不想要任何新奇的东西,您可以添加一个。您的
文档
将在每次添加或删除文本时触发一个UndoableEdit
。若要撤消并重做每次更改,请