希望我没听错,因为我不太明白您所说的“使用堆栈(不是摇摆)”是什么意思。 Stack 是一个数据结构,Swing 是一个 UI 框架。所以它们之间基本上没有任何关系。
实施撤消/重做通常使用以下方法之一来完成。您应该使用哪一个取决于您想要的撤消/重做行为。
使用命令模式撤消/重做。
实现这种方法看起来像这样:
public interface ICommand {
void do();
void undo();
}
public class StudentSaveCommand implements ICommand {
public StudentSaveCommand(Student student) { ... }
[...]
}
在StudentSaveCommand 类的do() 实现中,您实现了实际保存给定学生应采取的操作,例如将数据插入数据库,保存到文件或简单地将其添加到列表中。
在undo() 实现中,您执行操作以恢复do() 实现,例如从数据库中删除、删除文件或将其从列表中删除。
要最终使用Stacks 实现撤消/重做功能,您需要执行以下操作:
public void btnSaveStudentClickHandler() {
ICommand c = new IStudentSaveCommand(theStudentFromGUI);
c.do();
_redoStack.clear();
_undoStack.push(c);
}
public void btnUndoClickHandler() {
ICommand undoCommand = _undoStack.pop();
undoCommand.undo();
_redoStack.push(undoCommand);
}
public void btnRedoClickHandler() {
ICommand redoCommand = _redoStack.pop();
redoCommand.do();
_undoStack.push(redoCommand);
}
为了轻松地将模型上的更改反映到 GUI,我将实现/使用某种数据绑定。如您所见,这种方法不太适合在非常细粒度的级别上实现撤消/重做,例如在文本框中更改学生的姓名。第二种方法起作用了。
使用 Memento Pattern 撤消/重做。
使用此模式可以保存和恢复对象的状态,例如Student。使用此模式和Stacks 的撤消/重做功能的实现代码可能如下所示:
public void txtStudentNameLostFocusHandler() {
Memento sm = student.getSavedState();
_redoStack.clear();
_undoStack.push(sm);
}
public void btnUndoClickHandler() {
Memento m = _undoStack.pop();
student.restoreSavedState(m);
_redoStack.push(m);
}
// [...] Redo implementation straight-forward
为了反映对Student 对象所做的更改,我还希望数据绑定或实现如下方法,该方法必须在撤消/重做操作后调用:
public void updateStudentGUI(Student student) {
txtName.setText(student.getName());
[...]
}
要在您的撤消/重做实现中同时拥有这两种方法的优点,您还可以将它们结合起来。但是,最佳方法在很大程度上取决于规范,分别是您真正想要实现的目标。