JAVA 实现Undo/Redo(撤销/恢复)二
三, DrawLineCommand,实现一次Undo/Redo功能
一个继承了UndoableCommand提供具体的撤销/恢复功能的子类,就可以实现一次Undo/Redo。这里实现一个在容器上画直线的子类DrawLineCommand,带有擦除和重画直线的功能。
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.util.Random;
public class DrawLineCommand extends UndoableCommand {
private int x1, y1, x2, y2;
private Container container;
public DrawLineCommand(Container container) {
this.container = container;
x1 = new Random().nextInt(100) + 100;
y1 = new Random().nextInt(100) + 100;
x2 = new Random().nextInt(100) + 300;
y2 = new Random().nextInt(100) + 250;
}
@Override
public void command() {
drawLine(Color.RED);
System.out.print("Draw a ");
System.out.println(toString());
}
@Override
public void restore() {
drawLine(container.getBackground());
System.out.print("Erase the ");
System.out.println(toString());
}
private void drawLine(Color c) {
Graphics g = container.getGraphics();
g.setColor(c);
g.drawLine(x1, y1, x2, y2);
g.dispose();
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("line between point(");
stringBuilder.append(x1).append(",").append(y1).append(") and point(");
stringBuilder.append(x2).append(",").append(y2).append(")");
return stringBuilder.toString();
}
}
下面给出一个UndoTest类来测试DrawLineCommand
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class UndoTest extends JFrame {
UndoableCommand command;
Action drawLineAction, undoAction, redoAction;
public UndoTest() {
undoAction = new AbstractAction("Undo") {
@Override
public void actionPerformed(ActionEvent e) {
command.undo();
setEnabled(false);
redoAction.setEnabled(true);
}
};
undoAction.setEnabled(false);
redoAction = new AbstractAction("Redo") {
@Override
public void actionPerformed(ActionEvent e) {
command.redo();
setEnabled(false);
undoAction.setEnabled(true);
}
};
redoAction.setEnabled(false);
drawLineAction = new AbstractAction("Draw Line") {
@Override
public void actionPerformed(ActionEvent e) {
command = new DrawLineCommand(getContentPane());
command.execute();
undoAction.setEnabled(true);
}
};
}
public void createAndShowGUI() {
JToolBar toolBar = new JToolBar();
toolBar.add(drawLineAction);
toolBar.add(undoAction);
toolBar.add(redoAction);
add(toolBar, BorderLayout.NORTH);
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new UndoTest().createAndShowGUI();
}
});
}
}
结果:DrawLineCommand能完美完成最近一次的Undo/Redo
可见,用UndoableCommand来实现一次Undo/Redo功能是可行的,那么如何实现多次或者无限制的Undo/Redo呢?