如何在Java中为MVC模型实现undo / redo?

时间:2012-10-07 21:02:19

标签: java swing model-view-controller undo-redo

我无法使用UndoManager理解撤消/重做功能,并将其与MVC模型集成。

我不知道在哪里放置各种方法(在模型,视图或控件中) 我仍然不确定如何使用撤消管理器。

我的控件类实现了UndoableEditListener 它创造了:

private UndoManager manager = new UndoManager();

并在:

public void actionPerformed(ActionEvent e) {
   if (e.getActionCommand().equals("Undo")) {    
      try {
          manager.undo();   
      } catch (CannotUndoException ex) { 
          ex.printStackTrace(); 
      }
   }
}

我理解到这里,但其余的我不知道该怎么做。我知道我将不得不在模型和视图类中添加更多内容,但不确定在哪里。 我必须拥有以下课程吗?

public class UndoAction extends AbstractAction {}

public void undoableEditHappened(UndoableEditEvent e) {

我只是在文本字段中放置一个整数,然后我希望能够撤消这个。我在视图类的文本字段中设置数字。我想以最简单的方式实现这一点,没有花哨的编码!这是我的屁股的一小部分,但我不能让它工作!!

=============================================== =========== 以下是我的代码的更详细说明,也许会有所帮助:

我有一个模型,视图和控制包。

Contol有: ButtonGUIControl.java,它实现了两个

    ActionListener and 
    UndoableEditListener.


    final UndoManager manager = new UndoManager();

在actionPerformed方法中,它调用

    if (e.getActionCommand().equals("Undo")){

             try {

                    manager.undo();
                }

并在:

    public void undoableEditHappened(UndoableEditEvent evt) {
          manager.addEdit(evt.getEdit());

}

在视图中: 扩展JTextField的Grid.java将添加以下内容,只需在GUI上显示一个数字:(模型只是我的Model类的一个实例)

    getDocument().addUndoableEditListener(new ButtonGUIControl(model));

可能是因为UndoManager是在另一个包中创建的吗?我真的不知道如何调试它了!!

如果有帮助,我可以发布我的整个代码。我想我不知道如何将它与我的mvc模型结构相结合。

2 个答案:

答案 0 :(得分:3)

退一步。这里的整个想法是用户将使用您的应用程序,并将对某些内容进行一系列更改。文本编辑器就是一个很好的例子。您可以插入字符和行,再次删除它们,用其他文本替换文本,滚动文本等。为了通过MVC支持这一点,您有一个保存状态的模型和一个显示它的视图。

您的第一直觉可能是让视图直接访问模型,然后在每次用户进行更改时刷新视图,但使用该实现撤消这些更改非常困难。相反,您可以对用户在能够执行该更改的类中进行的各种更改进行编码,然后可以撤消该更改。

例如,插入文本的操作将由知道插入点的字符偏移量和要插入的字符串的类实现。执行操作会将字符串插入偏移量,撤消操作将在该插入点之后删除正确数量的字符。你有一个不同的类可以处理删除,另一个类可以处理滚动等。

每次用户执行某些操作时,视图都会构造其中一个UndoableEdit类,并告诉实例自行运行(redo())。一旦执行,您将UndoableEdit放在UndoableEdit实例列表的末尾,这些实例表示用户到目前为止所执行的所有操作。此列表使得很容易支持任何撤消请求,重做请求和实际编辑操作序列(导致更多UndoableEdit被放在列表中)。

回到你的问题。如果你的应用需要支持undo和redo,那么你需要实现一个UndoManager,它只管理UndoableEdit的列表并根据需要执行undo和redo。您还必须实现一大堆UndoableEdits,用于您的用户将针对UI执行的各种操作。至于听众,我看不出你真的需要这样做。

答案 1 :(得分:1)

  1. 如果您只需要简单的撤消/重做,您可以按原样使用UndoManager,不需要以任何方式对其进行子类化或自定义。
  2. JTextField(更具体地说是它的模型,Document)有一些内置的undo支持,这意味着你不需要编写UndoableEdit实现,UndoableEdit对象将自动创建为你(实际上AbstractDocument.DefaultDocumentEvent实现UndoableEdit)。
  3. 完整简单的工作示例是here