JavaFX TextArea文本修改监听器:资源消耗困境

JavaFX TextArea Text Modification Listener: Resource Consumption Dilemma

我们能够处理 JavaFX TextArea 中所做的更改,如下所示: JavaFX TextArea onChange event

本质上,这个 'listener' 可以帮助我检查对 TextArea 进行更改前后的文本。

有时,只检查一个字符就够了,但是上述方法的实现方式,它会抓取整个字符串的前后。比如我想实现一个持久化的缩进,我的逻辑是:

  1. 我保留了一个初始值为 0 的制表符计数器。
  2. 如果输入 \t 个字符,那么我每次都会递增该值。
  3. 在输入 \n 后,下一行中预置了 \t 个字符。
  4. 如果按下 BACKSPACE 键(为简单起见,我们将此视为删除文本的唯一选项),然后我检查前一个字符,如果它是 \t 则我递减每次值等等。

但是,我觉得 Java 像之前和之后的值一样抓取整个文本内容使用太多资源,而不是只抓取一个字符。所以,

在文本区域的 textProperty() 上使用 ChangeListener 不是受支持的方式来执行您想要的操作。它创建了不必要的复杂逻辑:通过修改 textProperty() 上的侦听器内的文本,您会在 属性 本身被更改时触发对 属性 的另一个更改。简而言之,您对用户更改文本(实际 属性 已更改)作出反应,然后再次修改文本以表示您想要的内容。

例如,如果您在 textProperty() 中注册了不同的侦听器或绑定到它,则该侦听器或绑定会观察到文本的两个更改:第一个(“无效”在感觉你想让文本看起来像什么)由用户引起,其次,恢复到你真正想要的样子,由你的监听器中的代码引起。

不清楚您指的是什么“资源”:在最坏的情况下,我只能在文本区域中看到一个额外的、非常临时的文本副本;但即便如此,这似乎也不太可能 - 那个(临时)副本可能无论如何都存在。

所以不在 textProperty() 上使用侦听器的原因与机器资源或性能无关;它与您的应用程序逻辑以及您希望 textProperty() 假定的值序列有关。您希望 属性 依次采用最终用户看到的值,而不是采用您想要用代码“更正”的值。

实现的方法是使用 TextFormatter:

textArea.setTextFormatter(new TextFormatter<String>(change -> {
    // examine change and modify it if necessary...
    return change ;
}));

提供给 TextFormatter 构造函数的过滤器采用 TextFormatter.Change 对象,该对象封装了文本中建议的更改(即当前文本和新文本之间的建议差异)。这是在修改实际文本之前调用的。这意味着在您的实施中,您可以根据需要修改该更改,这正是您的用例。 (您可以通过返回 null 来完全否决更改,即不允许更改。)使用这种方法,文本区域的 text 属性 将从当前值转换为由用户的输入加上您的代码所做的修改,没有中间值。

有关如何使用 TextFormatter.Change 对象的详细信息,请参阅上面链接的文档。