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 it.
5 Answers
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.

- 13,303
- 18
- 49
- 71

- 2,816
- 1
- 22
- 24
-
1Here is a link with a more complete example: http://www.java-forums.org/javax-swing/9570-undo-redo-jtextarea.html – Petar Minchev Mar 30 '10 at 18:05
-
@Petar The code behind your link doesn't handle what happens when all the text is selected and replaced with the clipboard's content. What happens is the text area is emptied instead of being replaced with its former content. Repro: (1) put something in the clipboard, (2) select all characters in the text area, (3) press ^V to paste the clipboard over the selected content. I don't know yet what's going on but I intend to find out. The same goes for the code behind the link posted in this answer. I have a feeling the problem is the definition of "previous content". – Jeff Holt Oct 04 '17 at 18:50
-
The problem is that when you select all text and press ^V (paste), there are two events logged not one. The first event is a delete all event and the second is an insert event. – Jeff Holt Oct 04 '17 at 19:01
-
1@PetarMinchev The answer is [here](https://stackoverflow.com/questions/24433089/jtextarea-settext-undomanager) where we see how to override the replace method in a PlainDocument. – Jeff Holt Oct 04 '17 at 19:26
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));

- 7,417
- 6
- 40
- 55
-
is `UndoManagerHelper` class user defined? I'm not getting autocompletion for it in eclipse. I have also searched oracle java documentation but unable to find that class. I'm using java 8 – Omkar76 Aug 22 '20 at 09:24
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.

- 233
- 1
- 4
-
4+1, who is the person that downvoted this?? The tutorial has a working example and explains what is going on, which most certainly answers the question. Now it is up to the OP to read the tutorial, in fact the OP should have read the tutorial first before posting this question. In fact, if the user wasn't aware of the Swing tutorial before they know have access to a valuable reference that can help on future questions. This is the way all questions should be answered. – camickr Mar 30 '10 at 21:33
-
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);
}
}

- 413
- 3
- 7
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) {}
}
});

- 1,663
- 20
- 25