撤销和重做功能在很多软件都是非常普遍的,这里记录一下JavaFX实现撤销和重做功能的一种方案:
1. 接口定义
对于所有能执行撤销和重做的动作定义统一的接口:
public interface Undo {
void execute();
void undo();
void redo();
}
2. UndoManager
要实现撤销(undo)和重做(redo),需要一个UndoManager来管理所有Undo和Redo,这个UndoManager是整个撤销和重做的核心,下面是具体的实现代码:
public class UndoManager {
private static final UndoManager instance = new UndoManager(30);
public static UndoManager getInstance() {
return instance;
}
private final int maxSize;
private final List<Undo> undoStack = new ArrayList<>();
private final List<Undo> redoStack = new ArrayList<>();
public UndoManager(int maxSize) {
this.maxSize = maxSize;
}
public void push(Undo undo) {
undo.execute();
undoStack.add(0, undo);
if (undoStack.size() > maxSize) {
undoStack.remove(undoStack.size() - 1);
}
redoStack.clear();
}
public void clear() {
undoStack.clear();
redoStack.clear();
}
public boolean canUndo() {
return !undoStack.isEmpty();
}
public void undo() {
final Undo undo = undoStack.get(0);
undo.undo();
undoStack.remove(0);
redoStack.add(0, undo);
}
public boolean canRedo() {
return !redoStack.isEmpty();
}
public void redo() {
final Undo undo = redoStack.get(0);
undo.redo();
redoStack.remove(0);
undoStack.add(0, undo);
}
}
3. 使用UndoManager
UndoManager的使用非常简单,直接通过UndoManager.getInstance()获取实例即可,默认情况下支持撤销的次数为30。
下面是一个使用例子:
public class Sample02 extends Application {
@Override
public void start(Stage stage) {
UndoManager undoManager = UndoManager.getInstance();
StackPane root = new StackPane();
VBox container = new VBox();
container.setSpacing(10);
container.setAlignment(Pos.CENTER);
root.getChildren().add(container);
Button btn = new Button("新增文本");
AtomicInteger inc = new AtomicInteger(0);
btn.setOnMouseClicked(event -> undoManager.push(new TextUndo(container, new Label("米虫2022" + inc.incrementAndGet()))));
Button undo = new Button("撤销(undo)");
undo.setOnMouseClicked(event -> {
if (undoManager.canUndo()) {
undoManager.undo();
}
});
Button redo = new Button("重做(redo)");
redo.setOnMouseClicked(event -> {
if (undoManager.canRedo()) {
undoManager.redo();
}
});
container.getChildren().addAll(btn, undo, redo);
stage.setTitle("撤销 + 重做");
stage.setWidth(320);
stage.setHeight(480);
stage.setScene(new Scene(root));
stage.getIcons().clear();
stage.getIcons().add(new Image("logo.jpg"));
stage.show();
}
}
效果如下:
4. 监听
可以进一步完善UndoManager对外暴露变更属性,外部通过监听变更,跟无法undo或者redo时禁用相应的功能。
调整代码实现如下:
Button undo = new Button("撤销(undo)");
undo.setDisable(true);
undo.setOnMouseClicked(event -> {
if (undoManager.canUndo()) {
undoManager.undo();
}
});
Button redo = new Button("重做(redo)");
redo.setDisable(true);
redo.setOnMouseClicked(event -> {
if (undoManager.canRedo()) {
undoManager.redo();
}
});
undoManager.revisionProperty().addListener((ob, ov, nv) -> {
undo.setDisable(!undoManager.canUndo());
redo.setDisable(!undoManager.canRedo());
});
效果如下:
标签:undoManager,JavaFX,undo,new,UndoManager,redo,public From: https://www.cnblogs.com/michong2022/p/17034694.html