Swingで Undo Redo

テキストエディタ等でよくある、Undo(Ctrl-z)とRedo(Ctrl-y)をSwingで実現する。

主な構成要素

javax.swing.undo.UndoableEdit UndoRedoが行える編集作業そのものを表すインターフェース。メソッドundo(),redo()を持つ
javax.swing.event.UndoableEditListener UndoRedoが行える編集作業を監視するオブザーバを表すインターフェース。主な実装クラスとしては、UndoManagerクラスがある
javax.swing.event.UndoableEditEvent 編集作業発生時に、UndoableEditListenerに通知される、イベント。内部にUndoableEditを保持

関係

もう少し具体的な例

  1. GUI構築時に、編集対象であるJEditorPaneDocumentオブジェクトに、UndoableEditListenerの実装クラスであるUndoManagerオブジェクトを追加して、さらにUndoManagerに対してUndo、Redoを行うActionをそれぞれ作成して、ボタン等に割り当てておく。
  2. アプリケーションユーザーがそのJEditorPaneに対して編集を行った際、そのDocumentから、UndoManagerに対してUndoableEditEventが通知される。UndoManagerはUndoableEditEventから、UndoableEditを取得して管理する。
  3. Undoを行うActionが割り当てられたボタン等をアプリケーションユーザーがクリックした時に、UndoMangerへUndoを指示。UndoManager内部では最新のUndoableEditがUndoされる。
  4. Redoを行うActionが割り当てられたボタン等をアプリケーションユーザーがクリックした時に、UndoManagerへRedoを指示。UndoManager内部では直近にUndoされたUndoableEditがRedoされる。

サンプル

  //UndoMangerを保持するプロパティを宣言
  private UndoManager undomanager = new UndoManager();
  
  //このコードをGUI構築時に実行
  this.editorPane.getDocument().addUndoableEditListener(this.undomanager);

  //Undoのアクション/イベント処理に記述
  if (this.undomanager.canUndo()) this.undomanager.undo();

  //Redoのアクションイベント処理に記述
  if (this.undomanager.canRedo()) this.undomanager.redo();