对JTextArea使用undo和redo

时间:2010-03-30 17:55:14

标签: java swing

我正在使用Java swing制作文本编辑器。我正在使用JTextArea。我想知道如何在JTextArea中使用撤消和重做功能,因为我无法使用它。

5 个答案:

答案 0 :(得分:13)

据我了解,JTextArea没有内置的内置撤消/重做功能,但Google search找到this article可能会有所帮助。

javax.swing中显然存在Undo Manager,您可以连接到JTextArea的更改事件。

答案 1 :(得分:5)

自从我这样做以来已经有一段时间了,我不记得细节,但这里有一些信息链接:http://java.sun.com/docs/books/tutorial/uiswing/components/generaltext.html

向下滚动到标题为“收听文档更改”的部分以开始使用。

答案 2 :(得分:5)

你可以这样做

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

管理员附加到JTextArea的文档后,它将监视所有更改 到文本区域的内容。

将经理附加到文本组件后,您必须提供一些方法来说明 管理员撤消/重做操作。

在必要时调用UndoManager的public void undo()和public void redo()方法(例如actionlistener的actionPerformed()方法)

您可以通过以下方式将Action对象附加到按钮,而不是调用简化任务的undo()和redo()方法:

JButton undoButton = new JButton(UndoManagerHelper.getUndoAction(manager));
JButton redoButton = new JButton(UndoManagerHelper.getRedoAction(manager));

答案 3 :(得分:3)

我必须通过多个链接才能获得足够的帮助。我在这里添加了我成功实施的内容,以帮助未来的访问者。我使用JTextPane实现了这个,但我假设同样适用于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) {}
        }
    });

答案 4 :(得分:1)

我创建了一个简单的类,可以通过单个方法调用将撤消功能分配给JTextcomponent(JTextField,JTextArea等):

UndoTool.addUndoFunctionality(area);

或使用预先指定的撤消功能构造一个新的JTextArea:

UndoTool.createJTextFieldWithUndo();

这是实用程序类的实现:

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);
    }
}