JTextPane/JTextArea 中从未调用过 UndoableEditListener

UndoableEditListener never called in JTextPane/JTextArea

我正在尝试将 UndoableEditListener 附加到 JTextPaneJTextArea 以将编辑排队到 UndoManager.

textPane.getDocument().addUndoableEditListener(new UndoableEditListener() {
    @Override
    public void undoableEditHappened(UndoableEditEvent event) {
        undoQueue.addEdit(event.getEdit());
    }
});

但是当我在文本 window.

中键入 "aaa" 时,从未调用 undoableEditHappened

认为这是 Java 的错,不是我的错,我破解 AbstractDocument.class 使用 Eclipse 调试器打开以观察事件触发器。它有一个私有 listeners 数组。 AbstractDocument 将其所有侦听器存储在 listeners 数组的奇数索引中,侦听器的类型 Class<> 存储在偶数索引中。

protected void fireUndoableEditUpdate(UndoableEditEvent e) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length - 2; i >= 0; i -= 2) {
        if (listeners[i] == UndoableEditListener.class) {
            // Lazily create the event:
            // if (e == null)
            // e = new ListSelectionEvent(this, firstIndex, lastIndex);
            ((UndoableEditListener) listeners[i + 1]).undoableEditHappened(e);
        }
    }
}

看到第 if (listeners[i] == UndoableEditListener.class) 行了吗?当我添加撤消更改侦听器时,调试器显示包含我的侦听器的 listeners,以及它之前的索引中的 UndoableEditListener.class。但是,当调试器遇到该 if 语句时,数组 listeners 中的所有偶数索引在调试器中都显示为 DocumentListener.class。因此,if 语句始终是 false 而侦听器从未调用过。

到底是什么?这是 Java 8 错误吗?还是我错过了示例忘记提及的步骤?

问题出在 JTextPane。我重写了它的 setText 方法以强制它调用 readsetText 的替代方法,它在记住它们的同时规范化各种换行符。但是 JTextPane.read 似乎不会在文档上触发 UndoableEditEvent

如果我不理会 setText,那么 UndoManager.undo 就可以了。