首页 > 解决方案 > JavaFX TextArea 文本修改监听器:资源消耗困境

问题描述

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

本质上,这个“监听器”帮助我在对 TextArea 进行更改之前和之后检查文本。

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

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

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

标签: javajavafx

解决方案


ChangeListener在文本区域上使用 atextProperty()不是执行您想要的操作的受支持方式。它创建了不必要的复杂逻辑:通过修改 上的侦听器内的文本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对象的详细信息,请参阅上面链接的文档。


推荐阅读