我正在尝试编写一个支持某种着色的JTextPane:当用户输入文本时,我正在运行一些代码,根据某种算法为文本着色。这很有效。
问题是着色操作是使用撤消管理器(带有EventType.CHANGE的DefaultDocumentEvent)注册的。因此,当用户单击撤消时,着色消失。仅在第二个撤消请求时,文本本身才会回滚。
(请注意,着色算法有点慢,因此我无法在插入文本时对其进行着色。)
如果我试图阻止CHANGE事件到达撤消管理器,我会在几次撤消请求后得到异常:这是因为文档内容不符合可撤销编辑对象所期望的内容。
有什么想法吗?
答案 0 :(得分:1)
您是如何阻止CHANGE事件到达撤消管理器的?
在CHANGE排队后,您是否可以立即向UndoManager发送lastEdit()。die()调用?
答案 1 :(得分:1)
我只能假设你是如何进行文字着色的。如果您在StyledDocuments更改字符属性方法中执行此操作,则可以获取撤消侦听器并暂时从文档中取消注册该操作,然后一旦颜色更改已完成,则可以重新注册侦听器。
对于你想要做的事情应该没问题。
希望有所帮助
答案 2 :(得分:1)
在将isSignificant()
方法返回false
之前,您可以拦截CHANGE编辑并将每个编辑包装在另一个UndoableEdit中,然后再将其添加到UndoManager。然后每个撤消命令将撤消最近的INSERT或REMOVE编辑,以及自那时以来发生的每个CHANGE编辑。
最终,我认为你会发现JTextPane / StyledDocument / etc提供的样式机制。这种事情太有限了。它很慢,它使用太多内存,并且它基于用于跟踪文档词法结构的相同元素树。对于用户应用样式的应用程序(如文字处理器)而言,这是可以的(我猜),但对于必须在用户输入时不断更新样式的语法高亮显示器,这是可以的。
有几个基于Swing JTextComponent
,View
和Document
类的自定义实现的语法高亮编辑器的示例。像JEdit这样的一些实际上重新实现了整个javax.swing.text
包,但我认为你不需要走那么远。
答案 3 :(得分:0)
我刚刚遇到过这个问题。这是我的解决方案:
private class UndoManagerFix extends UndoManager {
private static final long serialVersionUID = 5335352180435980549L;
@Override
public synchronized void undo() throws CannotUndoException {
do {
UndoableEdit edit = editToBeUndone();
if (edit instanceof AbstractDocument.DefaultDocumentEvent) {
AbstractDocument.DefaultDocumentEvent event = (AbstractDocument.DefaultDocumentEvent) edit;
if (event.getType() == EventType.CHANGE) {
super.undo();
continue;
}
}
break;
} while (true);
super.undo();
}
@Override
public synchronized void redo() throws CannotRedoException {
super.redo();
int caretPosition = getCaretPosition();
do {
UndoableEdit edit = editToBeRedone();
if (edit instanceof AbstractDocument.DefaultDocumentEvent) {
AbstractDocument.DefaultDocumentEvent event = (AbstractDocument.DefaultDocumentEvent) edit;
if (event.getType() == EventType.CHANGE) {
super.redo();
continue;
}
}
break;
} while (true);
setCaretPosition(caretPosition);
}
}
它是我自定义JTextPane中的内部类,所以我可以在重做时修复插入位置。