如何在java中为动作实现简单的撤消/重做?

我已经创建了一个XML编辑器,我在最后阶段陷入困境:添加撤消/重做function。

当用户向JTree添加元素,属性或文本时,我只需要添加undo / redo。

我还是很新,但今天在学校我尝试(不成功)创建两个栈对象[],称为撤消和重做,并添加执行的动作。

例如,我有:

Action AddElement() { // some code public void actionPerformed(ActionEvent e) { performElementAction(); } } 

performElementAction实际上只是向JTree添加了一个Element。

我想添加一种方法来将此操作添加到我的撤消堆栈中。 是否只有一种简单的方法来实现undo.push(执行整个动作)或其他什么?

抱歉听起来像坏人,但这就是我:(

看一下Command Pattern ,它的用途包括实现undo / redofunction。

TL; DR:您可以通过实现Command和Memento模式( Design Patterns – Gama et.al )来支持撤消和重做操作。

纪念品模式

这种简单的模式允许您保存对象的状态。 只需将对象包装在一个新类中,并在其状态发生变化时更新它。

 public class Memento { MyObject myObject; public MyObject getState() { return myObject; } public void setState(MyObject myObject) { this.myObject = myObject; } } 

命令模式

Command模式存储原始对象(我们想要支持undo / redo)和memento对象,在撤消的情况下我们需要它。 此外,还定义了两种方法:

  1. 执行 :执行命令
  2. unExecute :删除命令

码:

 public abstract class Command { MyObject myObject; Memento memento; public abstract void execute(); public abstract void unExecute(); } 

定义扩展Command的逻辑“Actions”(例如Insert):

 public class InsertCharacterCommand extends Command { //members.. public InsertCharacterCommand() { //instantiate } @Override public void execute() { //create Memento before executing //set new state } @Override public void unExecute() { this.myObject = memento.getState()l } } 

应用模式:

最后一步定义了撤消/重做行为。 它们的核心思想是存储一堆命令,这些命令用作命令的历史列表。 要支持重做,只要应用撤消命令,就可以保留辅助指针。 请注意,无论何时插入新对象,都会删除其当前位置之后的所有命令; 这是通过下面定义的deleteElementsAfterPointer方法实现的:

 private int undoRedoPointer = -1; private Stack commandStack = new Stack<>(); private void insertCommand() { deleteElementsAfterPointer(undoRedoPointer); Command command = new InsertCharacterCommand(); command.execute(); commandStack.push(command); undoRedoPointer++; } private void deleteElementsAfterPointer(int undoRedoPointer) { if(commandStack.size()<1)return; for(int i = commandStack.size()-1; i > undoRedoPointer; i--) { commandStack.remove(i); } } private void undo() { Command command = commandStack.get(undoRedoPointer); command.unExecute(); undoRedoPointer--; } private void redo() { if(undoRedoPointer == commandStack.size() - 1) return; undoRedoPointer++; Command command = commandStack.get(undoRedoPointer); command.execute(); } 

结论:

使这个设计变得强大的是你可以添加任意数量的命令(通过扩展Command类),例如RemoveCommandUpdateCommand等等。 此外,相同的模式适用于任何类型的对象,使得设计可以在不同的用例中重复使用修改

本教程解释了命令模式的基本原理和Swing的撤消/重做机制。 希望能帮助到你。

我将尝试创建一个Action类,其中AddElementAction类inheritanceAction。 AddElementAction可以有一个Do()和Undo()方法,它可以相应地添加/删除元素。 然后,您可以为撤消/重做保留两个Actions堆栈,并在弹出它之前在顶部元素上调用Do()/ Undo()。

You have to define undo(), redo() operations along with execute() in Command interface itself

例:

 interface Command { void execute() ; void undo() ; void redo() ; } 

在ConcreteCommand类中定义一个State。 根据execute()方法之后的当前状态,您必须决定是否应将命令添加到Undo Stack或Redo Stack并相应地做出决定。

看看这个undo-redo命令文章,以便更好地理解。