【问题标题】:How to prevent the cursor from moving after undoing a Document.Replace如何在撤消 Document.Replace 后防止光标移动
【发布时间】:2011-07-27 00:43:38
【问题描述】:

如果您在 Java 中有一个文本组件并且您执行替换,则光标不会移动,如果您使用标准撤消管理器撤消和重做该替换,则光标将移动到该插入或删除的开头或结尾。

如何防止这种行为?

我能够使用 Java TextComponentDemo 触发此操作,我在其中添加了一个简单的替换操作来执行此操作:

doc.replace(doc.getText(0, doc.getLength()).indexOf("mouse"), 5, "cat", null);

如果我随后使用演示的撤消和重做,光标将移动。

【问题讨论】:

  • 重新格式化的代码;如果不正确,请恢复。
  • 尝试设置插入符号位置以恢复光标位置。

标签: java swing replace document undo


【解决方案1】:

Java Swing 并不是唯一在标准撤消管理器中具有此行为的 API。有时 XUL(它是 Firefox 和 Thunderbird 的基础)对第 3 方扩展中的文本区域做同样的事情。本质上,即使在这种情况下原始文本和替换文本相似,文本区域也必须将文档视为一个全新的文档,就像您执行了 select allpaste 覆盖旧文本。一般来说,将相同的光标位置恢复到新文档是没有用的,如果文档更短,甚至可能无法实现。

我认为解决此问题的最简单方法是创建您自己的自定义操作来替换文本。监听它们并执行操作,而不是执行默认操作。您的自定义操作应该是一个 compound 操作,它手动扫描文档,替换现有文档中的子字符串 - 通过执行许多文档更改,一直扫描并替换到最后。当您覆盖撤消方法时,只需浏览您所做的修改列表,以相反的顺序撤消每个修改。只要复合动作中的每个动作都正确设置了文本和光标位置,并且其undo方法正常工作,整个复合动作也将正常撤消。

This guide 应该希望能更清楚地解释这个概念。该示例在用户键入时将操作合并到组中。您只需要做同样的事情,但要进行程序编辑。

【讨论】:

    【解决方案2】:

    查看DefaultCaret 类中的caret update policy

    以下更新政策是 允许:

    • NEVER_UPDATE:插入符号在 文件,无论任何文件 更新,除非文档长度 变得小于当前插入符号 位置由于删除。在这种情况下 插入符号位置调整到末尾 的文件。插入符号不尝试 通过滚动保持自身可见 使用 this 时的关联视图 政策。
    • ALWAYS_UPDATE:插入符号始终跟踪文档更改。对于常规 改变它会增加它的位置,如果 插入发生在其之前或之前 当前位置,并减少 如果之前发生移除,则位置 它的当前位置。用于撤消/重做 更新它总是移动到 发生更新的位置。这 插入符号也试图保持自己 通过调用 adjustVisibility 可见 方法。
    • UPDATE_WHEN_ON_EDT:如果文档更新,则行为类似于 ALWAYS_UPDATE 在事件调度上执行 线程和喜欢 NEVER_UPDATE 如果 更新在其他线程上执行。

    您可以在撤消或重做操作之前将更新策略设置为NEVER_UPDATE,然后将其设置回操作之后的状态。

    public void actionPerformed(ActionEvent e) {
        int updatePolicy = caret.getUpdatePolicy();
        caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
        undoManager.undo();
        caret.setUpdatePolicy(updatePolicy);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-25
      • 2020-07-07
      • 2018-05-20
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多