#眉標= #副標=使用Java Swing輕鬆寫個Undoable程式(2) #大標=魔幻四重奏 #作者=文/侯捷 #引言= =============<程式1>======================= public void undo() throws CannotUndoException { if (!canUndo()) { throw new CannotUndoException(); } hasBeenDone = false; } =============<程式1 end>=============== =======<程式2>===================== public boolean canUndo() { return alive && hasBeenDone; } public boolean canRedo() { return alive && !hasBeenDone; } ======<程式2 end>================== =======<程式3>======================= public boolean isSignificant() { return true; } ========<程式3 end>======================= =======<程式4>========================= public void undo() throws CannotUndoException { super.undo(); int i = edits.size(); while (i-- > 0) { UndoableEdit e = (UndoableEdit)edits.elementAt(i); e.undo(); } } public void redo() throws CannotRedoException { super.redo(); Enumeration cursor = edits.elements(); while (cursor.hasMoreElements()) { ((UndoableEdit)cursor.nextElement()).redo(); } } =======<程式4 end >========================= =============<程式5>================== public UndoManager() { super(); indexOfNextAdd = 0; limit = 100; edits.ensureCapacity(limit); } public synchronized int getLimit() { return limit; } public synchronized void setLimit(int l) { if (!inProgress) throw …; limit = l; trimForLimit(); //以索引箭頭為中心左右各減少edits的個數 //使總體符合limit範圍內。 } =========<程式5 end>================== ===========<程式6>======================= public synchronized void undo() { ... UndoableEdit edit = editToBeUndone(); undoTo(edit); } protected void undoTo(UndoableEdit edit) { boolean done = false; while (!done) { UndoableEdit next = (UndoableEdit)edits.elementAt(--indexOfNextAdd); next.undo(); done = next == edit; } } =========<程式6 end>=================== =========<程式7>======================== public static void main(String args[]) { ... MyPanel myPanel = new MyPanel(); UndoManager manager = new UndoManager(); myPanel.addUndoableEditListener(manager); ... ==========<程式7 end>============== =======<程式8>===================== class MyPanel extends JPanel { UndoableEditSupport ues = new UndoableEditSupport(this); ... public void addUndoableEditListener(UndoableEditListener uel) { ues.addUndoableEditListener(uel); } =======<程式8 end>===================== ===========<程式9>================= public MyPanel() { MouseListener mouseListener = new MouseAdapter() { public void mouseReleased(MouseEvent mouseEvent) { ues.postEdit(new MyUndoableEdit(MyPanel.this)); ... } }; addMouseListener(mouseListener); } ===========<程式9end>================= ==========<程式10>========================= public class UndoManager extends CompoundEdit implements UndoableEditListener { ... public void undoableEditHappened(UndoableEditEvent e) { addEdit(e.getEdit()); } } ==========<程式10 end>========================= ======<程式11>==================================== JToolBar toolbar = new JToolBar(); toolbar.add(UndoManagerHelper.getUndoAction(manager)); toolbar.add(UndoManagerHelper.getRedoAction(manager)); //以下建立frame並令其content內含一個toolbar JFrame frame = new JFrame("Drawing Sample"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container content = frame.getContentPane(); content.add(toolbar, BorderLayout.NORTH); content.add(drawingPanel, BorderLayout.CENTER); frame.setSize(300, 150); frame.setVisible(true); =======<==========<程式11 end>========================= ===========<程式12>=================== class MyUndoableEdit extends AbstractUndoableEdit { MyPanel panel; Polygon polygon, savedPolygon; public MyUndoableEdit(MyPanel panel) { this.panel = panel; polygon = panel.getPolygon(); //記錄當時的多邊形 } ===========<程式12 end>=================== =============<程式13>=================== public MyPanel() { MouseListener mouseListener = new MouseAdapter() { public void mouseReleased(MouseEvent mouseEvent) { ues.postEdit(new MyUndoableEdit(MyPanel.this)); //以上記錄好當時的多邊形後,才新增頂點並重繪,如下 polygon.addPoint(mouseEvent.getX(), mouseEvent.getY()); repaint(); } }; addMouseListener(mouseListener); } =============<程式13 end>=================== ========<程式14>===================== public void undo() throws CannotUndoException { super.undo(); savedPolygon = panel.getPolygon(); //記錄當時的多邊形 panel.setPolygon(polygon); //把先前記錄的多邊形拿出來用 } public void redo() throws CannotRedoException { super.redo(); panel.setPolygon(savedPolygon); //把undo前的多邊形拿出來用 savedPolygon = null; } ========<程式14 end>===================== =============== #相關資訊 以下是與本文主題相關的書籍資源。 * 《Java Swing》2/e, by Marc Loy, etc. O'Reilly, 2003. * 《Swing》2/e, by Matthew Robinson & Pavel Vorobive. Manning, 2003. * 《Definitive Guide to Swing for Java 2》3e, by John Zukowski. APress, 2005 ===============================