5

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

问题是着色操作是在撤消管理器中注册的(带有 EventType.CHANGE 的 DefaultDocumentEvent)。因此,当用户单击撤消时,着色消失。只有在第二个撤消请求时,文本本身才会回滚。

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

如果我试图阻止 CHANGE 事件到达撤消管理器,我会在多次撤消请求后得到一个异常:这是因为文档内容不符合 undoable-edit 对象所期望的内容。

有任何想法吗?

4

4 回答 4

1

您如何尝试阻止 CHANGE 事件到达撤消管理器?

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

于 2009-01-06T20:09:15.053 回答
1

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

对于您在那里尝试做的事情应该没问题。

希望有帮助

于 2009-01-07T02:38:41.103 回答
1

您可以拦截 CHANGE 编辑并将每个编辑包装在另一个 UndoableEdit 中,该isSignificant()方法返回false,然后将其添加到 UndoManager。然后每个撤消命令将撤消最近的 INSERT 或 REMOVE 编辑,以及此后发生的每个 CHANGE 编辑。

最终,我想你会发现 JTextPane/StyledDocument/etc 提供的样式机制。对于这种事情来说太有限了。它很慢,占用了太多内存,而且它基于用于跟踪文档词法结构的相同元素树。对于用户应用样式的应用程序(例如文字处理器)来说,这没问题(我猜),但对于必须在用户键入时不断更新样式的语法高亮器来说却不是。

有几个基于 Swing 和类的自定义实现的语法高亮编辑JTextComponentView示例Document。有些,比如 JEdit,实际上重新实现了整个javax.swing.text包,但我认为你不需要走那么远。

于 2009-01-07T15:15:41.417 回答
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 中的一个内部类,因此我可以在重做时修复插入符号的位置。

于 2014-03-14T06:45:53.607 回答