对于许多应用,如果能为用户提供Undo/Redo即撤消/重做的功能将会是很方便的。一般的解决方法都是自己定义一系列类来实现。在Swing中提供了专门实现Undo/Redo功能的javax.swing.undo包,使用该包(package)来为您的Java应用增加Undo/Redo功能将是非常的方便。研究过JDK demo的朋友应该记得在jfc demo Notepad中已经有过使用。其实UndoManager的功能并不限于文本编辑的功能, 本文将结合一简单示例具体介绍一下如何使用该类及相关接口来完成任意的Undo/Redo功能。
javax.swing.undo包中的主要的类及接口的简单介绍
StateEditable:接口,表达了一个状态可被StateEdit类改变的Object
UndoableEdit:接口,表达了一个已经完成的编辑操作(edit),而该操作可以被Undo/Redo.
StateEdit:表达了一个改变状态的编辑操作(edit)
UndoManager:负责实现undo/redo的功能,内部的成员包括了一个Vector,该Vector包含了所以已做过的操作,通过addEdit方法将已进行过的操作加入该类即可以通过调用undo和redo方法来实现Undo/Redo.
Swing提供的undo/redo功能的类及接口都在javax.swing.undo这一package中,所有的操作都通过实现UndoableEdit接口来表达。UndoableEdit接口定义了一个操作撤消或重做时需要执行的代码及相关信息。我们可以通过这中方法方便地实现几乎任意的Undo/Redo功能使用的步骤如下:
在程序中定义一UndoManager对象
建立一类继承UndoableEdit接口,并将undo/redo时需要执行的代码分别放在undo()和redo()方法中
在进行需要undo功能的操作时建立一以上所述类的实例,并加入到该UndoManager对象中
直接调用UndoManager对象的undo()和redo()方法即可实现Undo/Redo功能。
下面通过一具体程序代码来介绍如何使用
该程序代码是一个JApplet,界面如下
界面上面的部分为一个JPanel对象,主要用于显示画出的图形,下面的部分为四个按钮,点击"Draw Line"及"Draw Circle"按钮分别会在上面的JPanel中随机地绘制出直线和圆。所有的绘制操作都通过UndoableEdit接口记录在一UndoManager对象中,点击Undo或Redo按钮即可对刚才进行的操作进行撤消/重做。
下面我们通过代码的分析(完整代码附在文章之后)来看看怎么利用javax.swing.undo包来实现这一功能分步骤来看:
首先包含所需要的类,包括了JApplet所需要的一些包awt、net、swing等等,还包括了要用到的一些Utility.
在该JApplet的init方法中创建所有的UI对象及一个UndoManager对象。
对绘制圆和线的按钮注册如下形式的Listener
1 class LineListener implements ActionListener{
2 Shape temp;
3 public void actionPerformed(ActionEvent e){
4 temp = new Line2D.Double(0.0,0.0,Math.random()*100.0,Math.random()*100.0);
5 shapes.add(temp);
6 repaint();
7 UndoableEdit edit = new graphEdit(temp);
8 undomgr.addEdit(edit);
9 }
10
该Listener在用户按下按钮后先生成了一个图形对象(圆或直线),然后创建了一个UndoableEdit并添加到我们在上一步骤中创建的UndoManager对象中。而该继承UndoableEdit接口的类graphEdit的定义如下:
1 class graphEdit extends AbstractUndoableEdit{
2 Shape shape;
3 public graphEdit(Shape _shape){
4 shape = _shape;
5 }
6 public void undo(){
7 shapes.remove(shape);
8 repaint();
9 System.out.println("undo draw line");
10 }
11 public void redo(){
12 shapes.add(shape);
13 repaint();
14 System.out.println("redo draw line");
15 }
16 }
该graphEdit类实现了UndoableEdit中的undo和redo方法,其代码分别为将生成的图形去掉和重新加上,从这里我们就可以看到UndoManager实现的原理。我们在点击界面上的Undo/Redo按钮时,UndoManager对象中的undo和redo方法便被调用,而UndoManager中的方法再调用相应的UndoableEdit接口中undo及redo方法。
该代码示例只演示了如何使用javax.swing.undo包的最基本功能,其他的功能,还包括了getPresentationName(可以给每步操作加上适当的描述),undoTo,即可以一次进行多步undo/redo,有兴趣的朋友可以研究响应的文挡。 以下为该程序的完整代码及一些代码注释,其中有一些Java 2D的内容,如不熟悉,读者可不必深究 该JApplet需要编写一html文件以便AppletViewer或IE,Netscape运行,如何运行JApplet,读者可参考Java 2的文挡。
如您已经安装了Java 2 JRE,即可以在下面看到该Applet的完整代码