首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Swing 文字編輯器實作 Undo/Redo 功能完整範例

     編輯:Java 相關知識

前言

在開發文字編輯器時,撤銷與重做是基本且重要的功能。Java Swing 透過 javax.swing.undo 套件提供完整的支援,本文提供一個可直接套用的 UndoWrapper 類別,幫助您快速為 JEditorPane 或其他文字元件加入無限次數的 Undo/Redo 功能。

核心實作:UndoWrapper 類別

import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.JTextComponent;
import javax.swing.undo.*;

public class UndoWrapper implements UndoableEditListener {
    private UndoManager undoManager;
    private UndoAction undoAction;
    private RedoAction redoAction;
    private JEditorPane textComponent;

    public UndoWrapper(JEditorPane aComponent) {
        textComponent = aComponent;
        undoManager = new UndoManager();
        undoAction = new UndoAction();
        redoAction = new RedoAction();

        // 註冊編輯事件監聽器
        textComponent.getDocument().addUndoableEditListener(this);

        // 綁定快捷鍵:Ctrl+Z / Ctrl+Y
        textComponent.getInputMap().put((KeyStroke) undoAction.getValue(Action.ACCELERATOR_KEY), "undo");
        textComponent.getInputMap().put((KeyStroke) redoAction.getValue(Action.ACCELERATOR_KEY), "redo");
        textComponent.getActionMap().put("undo", undoAction);
        textComponent.getActionMap().put("redo", redoAction);
    }

    @Override
    public void undoableEditHappened(UndoableEditEvent e) {
        undoManager.addEdit(e.getEdit());
        undoAction.updateUndoState();
        redoAction.updateRedoState();
    }

    // 內部類別:Undo 動作
    class UndoAction extends AbstractAction {
        public UndoAction() {
            super("Cannot undo");
            setEnabled(false);
            putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl Z"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            try { undoManager.undo(); }
            catch (CannotUndoException cue) { cue.printStackTrace(System.err); }
            updateUndoState();
            redoAction.updateRedoState();
        }

        void updateUndoState() {
            if (undoManager.canUndo()) {
                setEnabled(true);
                putValue(Action.NAME, "Undo");
            } else {
                setEnabled(false);
                putValue(Action.NAME, "Cannot undo");
            }
        }
    }

    // 內部類別:Redo 動作
    class RedoAction extends AbstractAction {
        public RedoAction() {
            super("Cannot redo");
            setEnabled(false);
            putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl Y"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            try { undoManager.redo(); }
            catch (CannotRedoException cre) { cre.printStackTrace(System.err); }
            updateRedoState();
            undoAction.updateUndoState();
        }

        void updateRedoState() {
            if (undoManager.canRedo()) {
                setEnabled(true);
                putValue(Action.NAME, "Redo");
            } else {
                setEnabled(false);
                putValue(Action.NAME, "Cannot redo");
            }
        }
    }

    // 供外部選單/工具列呼叫
    UndoAction getUndoAction() { return undoAction; }
    RedoAction getRedoAction() { return redoAction; }
}

使用方式

只需一行程式碼即可啟用功能:

JEditorPane editorPane = new JEditorPane();
new UndoWrapper(editorPane);  // 完成!支援無限次 Undo/Redo

若需在選單或工具列加入按鈕,可呼叫 getUndoAction() 與 getRedoAction() 取得對應的 Action 物件。

關鍵技術點解析

  • UndoManager:核心管理類別,負責記錄編輯歷史並執行撤銷/重做邏輯。
  • UndoableEditListener:監聽 Document 的編輯事件,自動將每次編輯加入歷史堆疊。
  • Action 機制:透過 InputMap/ActionMap 綁定快捷鍵,並動態更新按鈕啟用狀態與顯示文字。
  • 異常處理:捕獲 CannotUndoException、CannotRedoException 避免程式異常中斷。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved