Java Tutorial/Swing/Redo Undo
Содержание
- 1 14. Adding Undo and Redo to a Text Component
- 2 14. Bind the undo action to ctl-Z
- 3 14. Create an undo action and add it to the text component
- 4 14. Create a redo action and add it to the text component (JTextComponent)
- 5 14. Listen for undo and redo events
- 6 14. Undoable Drawing
- 7 14. Undo Editor
- 8 14. Using the Undo Framework with Swing Text Components
14. Adding Undo and Redo to a Text Component
<source lang="java">
import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.KeyStroke; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import javax.swing.undo.UndoManager; public class Main{ public static void main(String[] argv) throws Exception{
JTextComponent textcomp = new JTextArea(); final UndoManager undo = new UndoManager(); Document doc = textcomp.getDocument(); JFrame f = new JFrame(); f.add(new JScrollPane(textcomp)); f.setSize(330,300); f.setVisible(true); doc.addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent evt) { undo.addEdit(evt.getEdit()); } }); textcomp.getActionMap().put("Undo", new AbstractAction("Undo") { public void actionPerformed(ActionEvent evt) { try { if (undo.canUndo()) { undo.undo(); } } catch (CannotUndoException e) { } } }); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo"); textcomp.getActionMap().put("Redo", new AbstractAction("Redo") { public void actionPerformed(ActionEvent evt) { try { if (undo.canRedo()) { undo.redo(); } } catch (CannotRedoException e) { } } }); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo");
}}</source>
14. Bind the undo action to ctl-Z
<source lang="java">
import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.KeyStroke; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import javax.swing.undo.CannotUndoException; import javax.swing.undo.UndoManager; public class Main {
public static void main(String[] argv) { JTextComponent textcomp = new JTextArea(); final UndoManager undo = new UndoManager(); Document doc = textcomp.getDocument(); doc.addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent evt) { undo.addEdit(evt.getEdit()); } }); textcomp.getActionMap().put("Undo", new AbstractAction("Undo") { public void actionPerformed(ActionEvent evt) { try { if (undo.canUndo()) { undo.undo(); } } catch (CannotUndoException e) { } } }); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo"); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(textcomp)); frame.setSize(380, 320); frame.setLocationRelativeTo(null); frame.setVisible(true); }
}</source>
14. Create an undo action and add it to the text component
<source lang="java">
import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import javax.swing.undo.CannotUndoException; import javax.swing.undo.UndoManager; public class Main {
public static void main(String[] argv) { JTextComponent textcomp = new JTextArea(); final UndoManager undo = new UndoManager(); Document doc = textcomp.getDocument(); doc.addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent evt) { undo.addEdit(evt.getEdit()); } }); textcomp.getActionMap().put("Undo", new AbstractAction("Undo") { public void actionPerformed(ActionEvent evt) { try { if (undo.canUndo()) { undo.undo(); } } catch (CannotUndoException e) { } } }); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(textcomp)); frame.setSize(380, 320); frame.setLocationRelativeTo(null); frame.setVisible(true); }
}</source>
14. Create a redo action and add it to the text component (JTextComponent)
<source lang="java">
import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.KeyStroke; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.text.Document; import javax.swing.text.JTextComponent; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import javax.swing.undo.UndoManager; public class Main {
public static void main(String[] argv) { JTextComponent textcomp = new JTextArea(); final UndoManager undo = new UndoManager(); Document doc = textcomp.getDocument(); doc.addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent evt) { undo.addEdit(evt.getEdit()); } }); textcomp.getActionMap().put("Undo", new AbstractAction("Undo") { public void actionPerformed(ActionEvent evt) { try { if (undo.canUndo()) { undo.undo(); } } catch (CannotUndoException e) { } } }); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo"); textcomp.getActionMap().put("Redo", new AbstractAction("Redo") { public void actionPerformed(ActionEvent evt) { try { if (undo.canRedo()) { undo.redo(); } } catch (CannotRedoException e) { } } }); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo"); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(textcomp)); frame.setSize(380, 320); frame.setLocationRelativeTo(null); frame.setVisible(true); }
}</source>
14. Listen for undo and redo events
<source lang="java">
public class Main{ public static void main(String[] argv){
JTextComponent textcomp = new JTextArea(); final UndoManager undo = new UndoManager(); Document doc = textcomp.getDocument(); doc.addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent evt) { undo.addEdit(evt.getEdit()); } }); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new JScrollPane(textcomp)); frame.setSize(380, 320); frame.setLocationRelativeTo(null); frame.setVisible(true);
}}</source>
14. Undoable Drawing
<source lang="java">
import java.awt.BorderLayout; import java.awt.ruponent; import java.awt.Graphics; import java.awt.Polygon; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Hashtable; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JToolBar; import javax.swing.UIManager; import javax.swing.event.UndoableEditListener; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import javax.swing.undo.StateEdit; import javax.swing.undo.StateEditable; import javax.swing.undo.UndoManager; import javax.swing.undo.UndoableEditSupport; public class UndoableDrawingPanel extends JPanel implements StateEditable {
private static String POLYGON_KEY = "Polygon"; UndoableEditSupport undoableEditSupport = new UndoableEditSupport(this); Polygon polygon = new Polygon(); public UndoableDrawingPanel() { MouseListener mouseListener = new MouseAdapter() { public void mouseReleased(MouseEvent mouseEvent) { StateEdit stateEdit = new StateEdit(UndoableDrawingPanel.this); polygon.addPoint(mouseEvent.getX(), mouseEvent.getY()); stateEdit.end(); undoableEditSupport.postEdit(stateEdit); repaint(); } }; addMouseListener(mouseListener); } public void addUndoableEditListener(UndoableEditListener undoableEditListener) { undoableEditSupport.addUndoableEditListener(undoableEditListener); } public void removeUndoableEditListener(UndoableEditListener undoableEditListener) { undoableEditSupport.removeUndoableEditListener(undoableEditListener); } public void storeState(Hashtable state) { state.put(POLYGON_KEY, getPolygon()); } public void restoreState(Hashtable state) { Polygon polygon = (Polygon) state.get(POLYGON_KEY); if (polygon != null) { setPolygon(polygon); } } public void setPolygon(Polygon newValue) { polygon = newValue; repaint(); } public Polygon getPolygon() { Polygon returnValue; if (polygon.npoints == 0) { returnValue = new Polygon(); } else { returnValue = new Polygon(polygon.xpoints, polygon.ypoints, polygon.npoints); } return returnValue; } protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawPolygon(polygon); } public static void main(String args[]) { JFrame frame = new JFrame("Drawing Sample2"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); UndoableDrawingPanel drawingPanel = new UndoableDrawingPanel(); UndoManager manager = new UndoManager(); drawingPanel.addUndoableEditListener(manager); JToolBar toolbar = new JToolBar(); JButton undoButton = new JButton(UndoManagerHelper.getUndoAction(manager)); toolbar.add(undoButton); JButton redoButton = new JButton(UndoManagerHelper.getRedoAction(manager)); toolbar.add(redoButton); frame.add(toolbar, BorderLayout.NORTH); frame.add(drawingPanel, BorderLayout.CENTER); frame.setSize(300, 150); frame.setVisible(true); }
} class UndoManagerHelper {
public static Action getUndoAction(UndoManager manager, String label) { return new UndoAction(manager, label); } public static Action getUndoAction(UndoManager manager) { return new UndoAction(manager, (String) UIManager.get("AbstractUndoableEdit.undoText")); } public static Action getRedoAction(UndoManager manager, String label) { return new RedoAction(manager, label); } public static Action getRedoAction(UndoManager manager) { return new RedoAction(manager, (String) UIManager.get("AbstractUndoableEdit.redoText")); } private abstract static class UndoRedoAction extends AbstractAction { UndoManager undoManager = new UndoManager(); String errorMessage = "Cannot undo"; String errorTitle = "Undo Problem"; protected UndoRedoAction(UndoManager manager, String name) { super(name); undoManager = manager; } public void setErrorMessage(String newValue) { errorMessage = newValue; } public void setErrorTitle(String newValue) { errorTitle = newValue; } protected void showMessage(Object source) { if (source instanceof Component) { JOptionPane.showMessageDialog((Component) source, errorMessage, errorTitle, JOptionPane.WARNING_MESSAGE); } else { System.err.println(errorMessage); } } } public static class UndoAction extends UndoRedoAction { public UndoAction(UndoManager manager, String name) { super(manager, name); setErrorMessage("Cannot undo"); setErrorTitle("Undo Problem"); } public void actionPerformed(ActionEvent actionEvent) { try { undoManager.undo(); } catch (CannotUndoException cannotUndoException) { showMessage(actionEvent.getSource()); } } } public static class RedoAction extends UndoRedoAction { public RedoAction(UndoManager manager, String name) { super(manager, name); setErrorMessage("Cannot redo"); setErrorTitle("Redo Problem"); } public void actionPerformed(ActionEvent actionEvent) { try { undoManager.redo(); } catch (CannotRedoException cannotRedoException) { showMessage(actionEvent.getSource()); } } }
}</source>
14. Undo Editor
<source lang="java">
import java.awt.BorderLayout; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.undo.UndoManager; public class UndoEditor extends JFrame {
private UndoManager undoManager = new UndoManager(); private JMenuBar menuBar = new JMenuBar(); private JMenu editMenu = new JMenu("Edit"); private UndoAction undoAction = new UndoAction(); private RedoAction redoAction = new RedoAction(); public UndoEditor() { setLayout(new BorderLayout()); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JTextPane editor = new JTextPane(); editor.getDocument().addUndoableEditListener(new UndoListener()); JScrollPane scroller = new JScrollPane(editor); menuBar.add(editMenu); editMenu.add(undoAction); editMenu.add(redoAction); this.setJMenuBar(menuBar); add(scroller); setSize(400, 300); setVisible(true); } public static void main(String[] args) { new UndoEditor(); } class UndoListener implements UndoableEditListener { public void undoableEditHappened(UndoableEditEvent e) { undoManager.addEdit(e.getEdit()); undoAction.update(); redoAction.update(); } } class UndoAction extends AbstractAction { public UndoAction() { this.putValue(Action.NAME, undoManager.getUndoPresentationName()); this.setEnabled(false); } public void actionPerformed(ActionEvent e) { if (this.isEnabled()) { undoManager.undo(); undoAction.update(); redoAction.update(); } } public void update() { this.putValue(Action.NAME, undoManager.getUndoPresentationName()); this.setEnabled(undoManager.canUndo()); } } class RedoAction extends AbstractAction { public RedoAction() { this.putValue(Action.NAME, undoManager.getRedoPresentationName()); this.setEnabled(false); } public void actionPerformed(ActionEvent e) { if (this.isEnabled()) { undoManager.redo(); undoAction.update(); redoAction.update(); } } public void update() { this.putValue(Action.NAME, undoManager.getRedoPresentationName()); this.setEnabled(undoManager.canRedo()); } }
}</source>
14. Using the Undo Framework with Swing Text Components
<source lang="java">
import java.awt.BorderLayout; import java.awt.ruponent; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JToolBar; import javax.swing.UIManager; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import javax.swing.undo.UndoManager; class UndoManagerHelper {
public static Action getUndoAction(UndoManager manager, String label) { return new UndoAction(manager, label); } public static Action getUndoAction(UndoManager manager) { return new UndoAction(manager, (String) UIManager.get("AbstractUndoableEdit.undoText")); } public static Action getRedoAction(UndoManager manager, String label) { return new RedoAction(manager, label); } public static Action getRedoAction(UndoManager manager) { return new RedoAction(manager, (String) UIManager.get("AbstractUndoableEdit.redoText")); } private abstract static class UndoRedoAction extends AbstractAction { UndoManager undoManager = new UndoManager(); String errorMessage = "Cannot undo"; String errorTitle = "Undo Problem"; protected UndoRedoAction(UndoManager manager, String name) { super(name); undoManager = manager; } public void setErrorMessage(String newValue) { errorMessage = newValue; } public void setErrorTitle(String newValue) { errorTitle = newValue; } protected void showMessage(Object source) { if (source instanceof Component) { JOptionPane.showMessageDialog((Component) source, errorMessage, errorTitle, JOptionPane.WARNING_MESSAGE); } else { System.err.println(errorMessage); } } } public static class UndoAction extends UndoRedoAction { public UndoAction(UndoManager manager, String name) { super(manager, name); setErrorMessage("Cannot undo"); setErrorTitle("Undo Problem"); } public void actionPerformed(ActionEvent actionEvent) { try { undoManager.undo(); } catch (CannotUndoException cannotUndoException) { showMessage(actionEvent.getSource()); } } } public static class RedoAction extends UndoRedoAction { public RedoAction(UndoManager manager, String name) { super(manager, name); setErrorMessage("Cannot redo"); setErrorTitle("Redo Problem"); } public void actionPerformed(ActionEvent actionEvent) { try { undoManager.redo(); } catch (CannotRedoException cannotRedoException) { showMessage(actionEvent.getSource()); } } }
} public class UndoSample {
public static void main(String args[]) { JFrame frame = new JFrame("Undo Sample"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JTextArea textArea = new JTextArea(); JScrollPane scrollPane = new JScrollPane(textArea); UndoManager manager = new UndoManager(); textArea.getDocument().addUndoableEditListener(manager); JToolBar toolbar = new JToolBar(); JButton undoButton = new JButton(UndoManagerHelper.getUndoAction(manager)); toolbar.add(undoButton); JButton redoButton = new JButton(UndoManagerHelper.getRedoAction(manager)); toolbar.add(redoButton); frame.add(toolbar, BorderLayout.NORTH); frame.add(scrollPane, BorderLayout.CENTER); frame.setSize(300, 150); frame.setVisible(true); }
}</source>