java - 一步而不是三步撤消 JEditorPane 的 setText() 方法的效果

标签 java swing

我正在尝试撤消 JEditorPane 中的 setText() 方法效果。这是我的代码:

public final class UndoManagerTestForJEditorPane {

private final JEditorPane editor = new JEditorPane();
private final UndoManager undoManager = new UndoManager();

public JComponent makeUI() {
    editor.setContentType("text/html");
    HTMLDocument document = (HTMLDocument) editor.getDocument();
    document.addUndoableEditListener(undoManager);
    editor.setText("Hello");

    JPanel p = new JPanel();
    p.add(new JButton(new AbstractAction("undo") {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (undoManager.canUndo()) {
                undoManager.undo();
            }
        }
    }));
    p.add(new JButton(new AbstractAction("redo") {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (undoManager.canRedo()) {
                undoManager.redo();
            }
        }
    }));
    p.add(new JButton(new AbstractAction("setText(new Date())") {
        @Override
        public void actionPerformed(ActionEvent e) {
            String str = new Date().toString();
            editor.setText(str);
        }
    }));

    Box box = Box.createVerticalBox();
    box.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    box.add(makePanel("Default", editor));

    JPanel pp = new JPanel(new BorderLayout());
    pp.add(box, BorderLayout.NORTH);
    pp.add(p, BorderLayout.SOUTH);
    return pp;
}

private static JPanel makePanel(String title, JComponent c) {
    JPanel p = new JPanel(new BorderLayout());
    p.setBorder(BorderFactory.createTitledBorder(title));
    p.add(c);
    return p;
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            createAndShowGUI();
        }
    });
}

public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new UndoManagerTestForJEditorPane().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
}
}

默认行为通过四个步骤完成:

1) 什么也没做,光标甚至没有移动..

2) 光标向下移动到插入的单词下方近 10 行..

3)文字消失了..

4)旧文本终于出现了..

因此,除了这些步骤之外,我们是否可以只使用一个撤消步骤来完成此操作,如 JTextField JTextArea setText() & UndoManager 的链接中所示。 ,但是使用 JEditorPane ?

在 JEditorPane 上调用 setText() 时,JEditorPane 的替换方法未执行的问题...

请帮忙吗?

谢谢

最佳答案

您可以使用扩展 AbstractUndoableEdit 的单独类(如果您只需使用一个类中的信息进行编辑,则可以嵌套以直接访问必要的 GUI 元素)来完成此操作。您可以保存在一次undo 操作后要加载的确切旧状态,以及在redo 操作后要重新加载的确切新状态。然后,您可以通过在 State 类中覆盖 redoundo 方法来直接在它们中设置正确的值。这可能看起来像这样:

public final class UndoManagerTestForJEditorPane {

private final JEditorPane editor = new JEditorPane();
private final UndoManager undoManager = new UndoManager();

public JComponent makeUI() {
    editor.setContentType("text/html");
    HTMLDocument document = (HTMLDocument) editor.getDocument();
    //document.addUndoableEditListener(undoManager);  -> Not used anymore
    editor.setText("Hello");

    JPanel p = new JPanel();
    p.add(new JButton(new AbstractAction("undo") {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (undoManager.canUndo()) {
                undoManager.undo();
            }
        }
    }));

    // New class to hold the state and load the correct string
    class State extends AbstractUndoableEdit
    {
        String oldText;
        String newText;

        State(String oldText, String newText)
        {
            this.oldText = oldText;
            this.newText = newText;
        }

        @Override
        public void undo() throws CannotUndoException {
            editor.setText(oldText);
        }

        @Override
        public boolean canUndo() {
            return true;
        }

        @Override
        public void redo() throws CannotRedoException {
            editor.setText(newText);
        }

        @Override
        public boolean canRedo() {
            return true;
        }


    }
    p.add(new JButton(new AbstractAction("redo") {
        @Override
        public void actionPerformed(ActionEvent e) {
            if (undoManager.canRedo()) {
                undoManager.redo();
            }
        }
    }));
    p.add(new JButton(new AbstractAction("setText(new Date())") {
        @Override
        public void actionPerformed(ActionEvent e) {
            String str = new Date().toString();
            // Add a new edit by saving the old string (by calling getText) and the new string 'str'
            undoManager.addEdit(new State(editor.getText(), str));
            editor.setText(str);
        }
    }));



    Box box = Box.createVerticalBox();
    box.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    box.add(makePanel("Default", editor));

    JPanel pp = new JPanel(new BorderLayout());
    pp.add(box, BorderLayout.NORTH);
    pp.add(p, BorderLayout.SOUTH);
    return pp;
}

private static JPanel makePanel(String title, JComponent c) {
    JPanel p = new JPanel(new BorderLayout());
    p.setBorder(BorderFactory.createTitledBorder(title));
    p.add(c);
    return p;
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            createAndShowGUI();
        }
    });
}

public static void createAndShowGUI() {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.getContentPane().add(new UndoManagerTestForJEditorPane().makeUI());
    f.setSize(320, 240);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
}
}

关于java - 一步而不是三步撤消 JEditorPane 的 setText() 方法的效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26983546/

相关文章:

java 枚举 : conceptual doubt

Java KeyListener,尝试根据按下的键改变颜色

java - 生成 JTextField 输入猜测

java - 分块传输编码时如何使用 HttpsUrlconnection 读取响应

java - 什么是NullPointerException,我该如何解决?

java - 如何判断gui是否完全用java构建?

java - JAVA动态改变标签框中字符的颜色

java - 如何区分 textField.setText() 和在 java 中手动向 textField 添加文本?

java - Java 程序中的 Unicode 转义行为

java - 我怎样才能返回正确的值?