我正在尝试将UndoableEditListener
附加到JTextPane
或JTextArea
,以便将编辑排入UndoManager
。
textPane.getDocument().addUndoableEditListener(new UndoableEditListener() {
@Override
public void undoableEditHappened(UndoableEditEvent event) {
undoQueue.addEdit(event.getEdit());
}
});
但是当我在文本窗口中键入"aaa"时,undoableEditHappened
永远不会被调用。
我认为这是Java的错,而不是我的错,所以我用Eclipse调试器打开AbstractDocument.class
来观察事件触发器。它有一个专用的listeners
阵列。AbstractDocument
将其所有侦听器存储在listeners
数组中的奇数索引中,侦听器的类型为Class<>'s在偶数指数中。
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)
行了吗?当我添加undo-change监听器时,调试器会显示包含我的监听器的listeners
,以及它之前的索引中的UndoableEditListener.class
。但是,当调试器使用if语句时,数组listeners
中的所有偶数索引在调试器中都显示为DocumentListener.class
。因此,if语句始终是false
,并且侦听器从未被调用。
怎么了?这是Java 8的错误吗?还是我错过了一个例子忘记提及的步骤?
问题出现在JTextPane
中。我重写了它的setText
方法,迫使它调用read
,这是setText
的替代方法,它在记住各种换行符的同时对它们进行规范化。但是JTextPane.read
似乎没有在文档上触发UndoableEditEvent
。
如果我不去管setText
,那么UndoManager.undo
就行了。