利用swing的undo包实现Undo/Redo功能

利用swingundo包实现Undo/Redo功能

 

一、概述

javax.swing.undo包提供了一系列接口和类,利用它可以方便的在程序中加入Undo/Redo功能。

 

先说说undo包引入的一个概念——Edit。它是与Command模式中的Command类似的一个概念。Command模式将操作的执行逻辑封装到一个个Command对象中,解耦了操作发起者和操作执行逻辑之间的耦合关系:操作发起者要进行一个操作,不用关心具体的执行逻辑,只需创建一个相应的Command实例,调用它的执行接口即可。而在swing中,与界面交互的各种操作,比如插入,删除等被称之为Edit,实际上就是Command

 

下面是undo包的几个主要接口和类:

UndoableEdit 顾名思义,它表示一个可以被Undo/Redo的操作;

AbstractUndoableEdit 实现UndoableEdit的抽象类;

UndoManager Undo/Redo管理器,各种UndoableEdit实例通过addEdit方法加入UndoManager,通过调用UndoManagerundo/redo方法来实现Undo/Redo功能。

 

使用undo包很简单,主要操作步骤如下:

1、创建UndoManager实例;

2、创建各种实现UndoableEdit的具体操作类;

3、调用某种操作时,创建一个具体操作类的实例,加入UndoManager

4、在Undo/Redo时,直接调用UndoManagerundo/redo方法。

 

二、应用实例

下面就以一个比较常见的例子结合上述的操作步骤来进行说明。

现有一个产品列表界面,提供插入,删除,移动产品位置等操作,这些操作均要可以撤消和重做。如下是该界面的截图:

 

以上产品列表界面中,具有添加,删除,上移,下移四个操作按钮和Undo/Redo两个按钮,产品列表用一个JList实现。

 

第一步、创建UndoManager实例。

SamplePanel是我们的产品列表界面实现类,因此我们在SamplePanel类的初始化中加入:

...

private UndoManager undoManager=new UndoManager();

...

 

第二步、定义添加,删除,上移,下移的具体操作类。

AddEdit类负责添加操作;

DeleteEdit类负责删除操作;

UpDownEdit类负责上移和下移操作。

 

swingMVC体系中,JList是一个View类,操作内部数据的能力来自于它的数据模型类ListModel。因此我们的每个具体操作类,如添加,删除等均通过直接操纵ListModel来达到目的。这是swing界面开发中的惯用做法。

 

为此,我们先定义一个抽象的ListEdit类,含有一个ListModel成员,供其他具体操作类继承。

public abstract class ListEdit extends AbstractUndoableEdit{

    //列表的数据模型

    protected DefaultListModel model=null;

    //操作的具体执行逻辑,留待子类实现

    public abstract void execute();

   

    //在这里,redo操作只是简单的执行一次execute。子类如无特殊需求,就不用覆盖它。

    public void redo() throws CannotRedoException {

        execute();

    }

}

 

下面来分别实现AddEditDeleteEditUpDownEdit类,它们均继承自ListEdit类。

我们在execute方法中实现操作逻辑,在undo方法中实现Undo的逻辑。redo方法在ListEdit中已经实现,不用管它了。

这里提一下如下两个方法:

getUndoPresentationName()getRedoPresentationName()方法可以为Undo/Redo操作提供描述。比如,如果要在菜单中提供撤消删除重做删除菜单项而不是简单的无所指的撤消重做菜单项,可以通过这两个方法来获得。

 

一个需要注意的问题是,在实现执行逻辑时要保留现场数据,以供Undo时按图索骥恢复现场。

比如,要执行Delete操作,我们要记住删除的元素和所在位置这两个现场数据,undo方法据此来在原位置插入被删除的元素。如果没有这两个现场数据,undo就无从下手了。

下面是DeleteEdit类的实现:

public class DeleteEdit extends ListEdit{

    //被删除的元素

    private Object element;

    //删除发生的位置

    private int index;

   

    public DeleteEdit(DefaultListModel model,int index) {

        this.model=model;

        this.index=index;

    }

   

    public void execute() {

        element=model.getElementAt(index);

        if(element!=null){

            model.removeElementAt(index);

        }

    }

 

    public void undo() throws CannotUndoException {

        if(element!=null){

            model.insertElementAt(element,index);

        }

    }

 

    public String getUndoPresentationName() {

        return "撤消删除元素";

    }

 

    public String getRedoPresentationName() {

        return "重做删除元素";

    }

}

其他操作类的实现原理基本类似,这里不再赘述。

 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
实现文本撤销、恢复功能可以使用Java Swing中提供的UndoManager类。该类是一个管理撤销、恢复操作的类,可以用来实现文本编辑器中的撤销、恢复功能。 下面是一个简单的示例代码,演示如何使用UndoManager实现文本撤销、恢复功能: ```java import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.undo.*; public class TextEditor extends JFrame { private JTextArea textArea; private UndoManager undoManager; public TextEditor() { textArea = new JTextArea(); undoManager = new UndoManager(); // 添加撤销、恢复操作监听器 textArea.getDocument().addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent e) { undoManager.addEdit(e.getEdit()); } }); // 添加菜单项和快捷键 JMenuBar menuBar = new JMenuBar(); JMenu editMenu = new JMenu("编辑"); JMenuItem undoItem = new JMenuItem("撤销"); undoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_MASK)); undoItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (undoManager.canUndo()) { undoManager.undo(); } } }); JMenuItem redoItem = new JMenuItem("恢复"); redoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_MASK)); redoItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (undoManager.canRedo()) { undoManager.redo(); } } }); editMenu.add(undoItem); editMenu.add(redoItem); menuBar.add(editMenu); setJMenuBar(menuBar); add(new JScrollPane(textArea)); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(400, 300); setVisible(true); } public static void main(String[] args) { new TextEditor(); } } ``` 在上述代码中,我们首先创建了一个JTextArea和一个UndoManager对象。然后,我们为JTextArea的Document添加了一个UndoableEditListener,监听文本编辑操作。每次用户进行文本编辑时,就会产生一个UndoableEditEvent事件,我们将该事件加入到UndoManager中,以便后续进行撤销、恢复操作。 接着,我们创建了一个菜单栏,并添加了“撤销”和“恢复”两个菜单项,分别对应undoManagerundo()和redo()方法。我们还为这两个菜单项添加了快捷键,方便用户使用。 最后,我们将JTextArea添加到JScrollPane中,并将其添加到窗口中显示。当用户进行文本编辑操作时,可以使用菜单栏或快捷键进行撤销、恢复操作。 希望这个示例代码对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值