gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-30 21:06:00 25 4
gpt4 key购买 nike

我已经创建了一个 XML 编辑器,但我停留在最后一个阶段:添加撤消/重做功能。

我只需要在用户向 JTree 添加元素、属性或文本时添加撤消/重做。

我在这方面还很陌生,但今天在学校我尝试(未成功)创建两个堆栈对象 [],称为撤消和重做,并将执行的操作添加到它们中。

例如,我有:

Action AddElement() {

// some code
public void actionPerformed(ActionEvent e) {

performElementAction();
}
}

performElementAction 实际上只是将一个元素添加到 JTree。

我想添加一种方法来将执行的此操作添加到我的撤消堆栈中。是否有一种简单的方法来撤消推送(执行的整个操作)或其他东西?

最佳答案

TL;DR:您可以通过实现命令 (p.233) 和 Memento (p.283) 模式 ( Design Patterns - Gamma et. al ) 来支持撤消和重做操作。

纪念品模式

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

public class Memento
{
MyObject myObject;

public MyObject getState()
{
return myObject;
}

public void setState(MyObject myObject)
{
this.myObject = myObject;
}
}

命令模式

命令模式存储原始对象(我们希望支持撤消/重做)和我们在撤消时需要的备忘录对象。此外,还定义了 2 个方法:

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

代码:

public abstract class Command
{
MyObject myObject;
Memento memento;

public abstract void execute();

public abstract void unExecute();
}

它们定义扩展命令的逻辑“ Action ”(例如插入):

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<Command> 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 等等。此外,相同的模式适用于任何类型的对象,使设计在不同的用例中可重用可修改

关于java - 如何在 Java 中为操作实现简单的撤消/重做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11530276/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com