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

本文详细介绍了如何利用Java Swing的undo包实现撤销/重做功能。通过创建UndoManager实例,定义各种操作类如AddEdit、DeleteEdit等,实现了列表中的添加、删除、上移和下移等操作的撤销和重做。文章通过实例展示了如何在操作中保存现场数据以备恢复,并提供了相关代码示例。
摘要由CSDN通过智能技术生成

利用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 "重做删除元素";

    }

}

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

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值