Java 对Swing'隐藏某些操作;s撤消管理器

Java 对Swing'隐藏某些操作;s撤消管理器,java,swing,undo,Java,Swing,Undo,我正在尝试编写一个JTextPane,它支持某种颜色:当用户键入文本时,我正在运行一些代码,根据某种算法为文本着色。这很有效 问题在于,着色操作是在undo manager(带有EventType.CHANGE的DefaultDocumentEvent)中注册的。因此,当用户单击“撤消”时,颜色将消失。只有在第二次撤消请求时,才会回滚文本本身 (请注意,着色算法有点慢,因此在插入文本时无法对其着色) 如果我试图阻止更改事件到达撤消管理器,则在多次撤消请求后会出现异常:这是因为文档内容不符合可撤消

我正在尝试编写一个JTextPane,它支持某种颜色:当用户键入文本时,我正在运行一些代码,根据某种算法为文本着色。这很有效

问题在于,着色操作是在undo manager(带有EventType.CHANGE的DefaultDocumentEvent)中注册的。因此,当用户单击“撤消”时,颜色将消失。只有在第二次撤消请求时,才会回滚文本本身

(请注意,着色算法有点慢,因此在插入文本时无法对其着色)

如果我试图阻止更改事件到达撤消管理器,则在多次撤消请求后会出现异常:这是因为文档内容不符合可撤消编辑对象的预期


有什么想法吗?

您是如何阻止更改事件到达撤消管理器的


您不能在更改排队后立即向UndoManager发送lastEdit().die()调用吗?

我只能假设您是如何进行文本着色的。如果您是在StyledDocuments change character属性方法中执行此操作,则可以获取撤消侦听器,并暂时从文档中注销该操作,然后在颜色更改完成后,可以重新注册侦听器

你在那里所做的一切都应该是好的


希望这对您有所帮助

您可以截取更改编辑,并在将其添加到UndoManager之前,将每个更改都包装在另一个UndoableEdit中,该UndoableEdit的
isSignificant()
方法返回
false
。然后,每个撤消命令将撤消最近的插入或删除编辑,以及此后发生的所有更改编辑

最终,我认为您会发现JTextPane/StyledDocument/等提供的样式化机制对于这种事情来说太有限了。它速度很慢,占用了太多内存,而且它基于用于跟踪文档词汇结构的同一个元素树。对于由用户应用样式的应用程序(如文字处理器),这是可以的(我猜),但对于必须随着用户键入而不断更新样式的语法高亮显示程序则不行


基于Swing
JTextComponent
View
Document
类的自定义实现,有几个语法突出显示编辑器的示例。有些人,比如JEdit,实际上重新实现了整个
javax.swing.text
包,但我认为您不需要走那么远。

我刚刚解决了这个问题。以下是我的解决方案:

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中的一个内部类,因此我可以在重做时修复插入符号位置。

不要这样做!!!这样做时,我遇到了一个非常糟糕的java内部异常。完整的Swing线程在我身上崩溃,每次重新绘制都会引发此异常:线程“AWT-EventQueue-0”java.lang.IllegalArgumentException中的异常:偏移量超出sun.util.locale.provider.RuleBasedBreakIterator.checkOffset(RuleBasedBreakIterator.java:759)的界限。对DefaultStyledDocument的执行给我带来了很多麻烦。当我更改样式时,我可以通过禁用撤消管理器来处理撤消/重做颜色问题。但是有明显的问题,因为当撤销/重做完成时,样式化文档并没有真正得到insertString调用——它似乎直接向文档的模型执行操作,这可能会在属性之间执行时破坏模型。如果在按下undo/redo时只调用DefaultStyledDocument上的那些方法,就会容易得多。