JavaFXTextArea文本修改侦听器:资源消耗困境

JavaFXTextArea文本修改侦听器:资源消耗困境,java,javafx,Java,Javafx,我们能够处理JavaFX文本区域中的更改,如下所示: 本质上,这个“监听器”帮助我在对TextArea进行更改之前和之后检查文本 有时,只检查一个字符就足够了,但按照前面提到的方法的实现方式,它会获取前后的整个字符串。例如,我希望实现一个持久缩进,我的逻辑是: 我保留一个初始值为0的制表符计数器 如果输入了\t字符,则每次递增该值 在输入\n时,许多\t字符被预先放置在下一行中 如果代码< >退格空间键被按下(为了简单起见,我们把它看作是删除文本的唯一选项),然后我检查前面的字符,如果它是 \

我们能够处理JavaFX文本区域中的更改,如下所示:

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

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

  • 我保留一个初始值为0的制表符计数器
  • 如果输入了
    \t
    字符,则每次递增该值
  • 在输入
    \n
    时,许多
    \t
    字符被预先放置在下一行中
  • 如果代码< >退格空间键被按下(为了简单起见,我们把它看作是删除文本的唯一选项),然后我检查前面的字符,如果它是<代码> \t>代码,那么每次我减值,等等。
  • 但是,我觉得Java像获取前后值一样获取整个文本内容会占用太多资源,而不仅仅是获取一个字符。所以

    • 实际上,这到底有多大区别?我假设在文本文件大约只有0.5MB左右的级别上,这将是相当资源密集型的
    • 如果有任何其他方法来实现侦听器,使其按照我想要的方式工作,那么当前方法将不接受除仅包含字符串的ObservableList对象之外的任何内容

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

    例如,如果您使用
    textProperty()
    注册了另一个侦听器,或对其进行了绑定,则该侦听器或绑定将观察到文本的两个更改:第一个更改是由用户引起的(在您希望文本外观的意义上为“无效”),第二个更改是恢复到您实际希望的内容,由侦听器中的代码引起

    现在还不清楚你指的是什么“资源”:在最坏的情况下,我只能在文本区域看到额外的、非常临时的文本副本;但即使这样似乎也不太可能——那个(临时的)拷贝无论如何都可能存在

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

    实现这一点的方法是使用
    TextFormatter

    textArea.setTextFormatter(new TextFormatter<String>(change -> {
        // examine change and modify it if necessary...
        return change ;
    }));
    
    textArea.setTextFormatter(新的TextFormatter(更改->{
    //检查更改并在必要时进行修改。。。
    回报变化;
    }));
    
    提供给
    TextFormatter
    构造函数的筛选器接受一个对象,该对象封装了文本中的建议更改(即当前文本和新文本之间的建议差异)。这是在修改实际文本之前调用的。这意味着在您的实现中,您可以在必要时修改该更改,这正是您的用例。(通过返回
    null
    ,您可以完全否决更改,即不允许更改)使用此方法,文本区域的
    text
    属性将从当前值转换为用户输入表示的值加上代码所做的修改,而不带中间值


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

    使用侦听器是完全错误的方法。改用
    TextFormatter
    ,并实现过滤器。请注意,逻辑可能需要比您描述的更复杂一些(无论您采用哪种方式处理);例如,如果选择了一大块文本,并复制另一个文本块,会发生什么情况。文本格式过滤器的过滤器通过了<代码>更改< /代码>实例,表示文本中建议的更改。现在还不清楚你在担心什么;然而,您使用的方法:“让用户更改文本,如果更改结果不是您想要的,则再次更改文本”显然是不雅观的。截取建议的更改并在将更改应用于文本之前对其进行修改正是文本格式化程序的设计目的。一般来说,您应该努力编写最干净、最符合逻辑的代码,并且只有在有实际证据表明这是一个问题时才担心性能。在这种情况下,使用文本格式化程序是最合乎逻辑的做法。但你担心什么资源?最糟糕的情况是,在调用事件侦听器的短时间内保留旧文本的副本。就这样。没有其他的“资源”是不会被使用的。这是一个已经实施了大约三十年的原则。你可以随心所欲地反对,但如果你是新手并且与整个行业意见相左,我谦恭地建议你得出自己的结论。文本区域实现的相关键和鼠标侦听器实现可能是这样的:键入键时,使用
    String oldText=getText()存储当前文本
    ,通过在插入符号处插入文本来更改文本,然后在每个
    ChangeListener
    上调用
    changed(textProperty(),oldText,getText())
    。如果这是我