Using undo and redo for JTextArea

后端 未结 5 948
一向
一向 2021-01-04 12:33

I am making a text editor using Java swing. I am using JTextArea for the same. I want to know how I can use Undo and Redo functionality in JTextArea as I am not able to use

相关标签:
5条回答
  • 2021-01-04 12:38

    You can do like this

    UndoManager manager = new UndoManager();
    textArea.getDocument().addUndoableEditListener(manager);
    

    Once the manager is attached to the document of the JTextArea, it will monitor all changes to the contents of the text area.

    After attaching the manager to the text component, you must provide some means to tell the manager to undo/redo an operation.

    Call the public void undo() and public void redo() method of the UndoManager where necessary(Eg. actionPerformed() method of an actionlistener)

    You can attach Action objects to a button in the following way instead of calling undo() and redo() methods which simplifies the task:

    JButton undoButton = new JButton(UndoManagerHelper.getUndoAction(manager));
    JButton redoButton = new JButton(UndoManagerHelper.getRedoAction(manager));
    
    0 讨论(0)
  • 2021-01-04 12:40

    I created a simple class that can assign undo functionality to a JTextcomponent (JTextField, JTextArea, etc.) with a single method call:

    UndoTool.addUndoFunctionality(area);
    

    or alternatively construct a new JTextArea with the undo functionality pre-assigned:

    UndoTool.createJTextFieldWithUndo();
    

    Here is the implementation of the utility class:

    public class UndoTool {
        private static final String REDO_KEY = "redo";
        private static final String UNDO_KEY = "undo";
    
        private JTextComponent component;
        private KeyStroke undo = KeyStroke.getKeyStroke("control Z");
        private KeyStroke redo = KeyStroke.getKeyStroke("control Y");
    
        public UndoTool(JTextComponent component) {
            this.component = component;
        }
    
        public void setUndo(KeyStroke undo) {
            this.undo = undo;
        }
    
        public void setRedo(KeyStroke redo) {
            this.redo = redo;
        }
    
        public static void addUndoFunctionality(JTextComponent component) {
            UndoTool tool = new UndoTool(component);
            UndoManager undo = tool.createAndBindUndoManager();
            tool.bindUndo(undo);
            tool.bindRedo(undo);
        }
    
        public static JTextArea createJTextAreaWithUndo() {
            JTextArea area = new JTextArea();
            addUndoFunctionality(area);
            return area;
        }
    
        public static JTextField createJTextFieldWithUndo() {
            JTextField field = new JTextField();
            addUndoFunctionality(field);
            return field;
        }
    
        public UndoManager createAndBindUndoManager() {
            Check.notNull(component);
    
            UndoManager manager = new UndoManager();
            Document document = component.getDocument();
            document.addUndoableEditListener(event -> manager.addEdit(event.getEdit()));
            return manager;
        }
    
        public void bindRedo(UndoManager manager) {
            component.getActionMap().put(REDO_KEY, new AbstractAction(REDO_KEY) {
                @Override
                public void actionPerformed(ActionEvent evt) {
                    try {
                        if (manager.canRedo()) {
                            manager.redo();
                        }
                    } catch (CannotRedoException ignore) {
                    }
                }
            });
            component.getInputMap().put(redo, REDO_KEY);
        }
    
        public void bindUndo(UndoManager manager) {
            component.getActionMap().put(UNDO_KEY, new AbstractAction(UNDO_KEY) {
                @Override
                public void actionPerformed(ActionEvent evt) {
                    try {
                        if (manager.canUndo()) {
                            manager.undo();
                        }
                    } catch (CannotUndoException ignore) {
                    }
                }
            });
            component.getInputMap().put(undo, UNDO_KEY);
        }
    }
    
    0 讨论(0)
  • 2021-01-04 12:44

    Its been a while since I did this and I dont recall the details, but here is a link with some info: http://java.sun.com/docs/books/tutorial/uiswing/components/generaltext.html

    Scroll down to the section titled "Listening for Changes on a Document" to get started.

    0 讨论(0)
  • 2021-01-04 12:59

    As I understand it, JTextArea has no inherent Undo/Redo functionality built in, but a Google search did find this article which might be helpful.

    There apparently exists an Undo Manager in javax.swing which you can hook up to the JTextArea's change events.

    0 讨论(0)
  • 2021-01-04 12:59

    I had to go through multiple links just to get enough help. I'm adding here what I implemented successfully just to help future visitors. I implemented this using JTextPane but am assuming the same would apply for the JTextArea

        JTextArea textArea = new JTextArea();
        JButton undo = new JButton("Undo");
        JButton redo = new JButton("Redo");
        KeyStroke undoKeyStroke = KeyStroke.getKeyStroke(
                KeyEvent.VK_Z, Event.CTRL_MASK);
        KeyStroke redoKeyStroke = KeyStroke.getKeyStroke(
                KeyEvent.VK_Y, Event.CTRL_MASK);
    
        UndoManager undoManager = new UndoManager();
    
        Document document = textArea.getDocument();
        document.addUndoableEditListener(new UndoableEditListener() {
            @Override
            public void undoableEditHappened(UndoableEditEvent e) {
                undoManager.addEdit(e.getEdit());
            }
        });
    
        // Add ActionListeners
        undo.addActionListener((ActionEvent e) -> {
            try {
                undoManager.undo();
            } catch (CannotUndoException cue) {}
        });
        redo.addActionListener((ActionEvent e) -> {
            try {
                undoManager.redo();
            } catch (CannotRedoException cre) {}
        });
    
        // Map undo action
        textArea.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
                .put(undoKeyStroke, "undoKeyStroke");
        textArea.getActionMap().put("undoKeyStroke", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    undoManager.undo();
                 } catch (CannotUndoException cue) {}
            }
        });
        // Map redo action
        textArea.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
                .put(redoKeyStroke, "redoKeyStroke");
        textArea.getActionMap().put("redoKeyStroke", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    undoManager.redo();
                 } catch (CannotRedoException cre) {}
            }
        });
    
    0 讨论(0)
提交回复
热议问题