JavaFX TextArea 和自动滚动

新手上路,请多包涵

我正在尝试使用通过事件处理程序放入的新文本让 TextArea 自动滚动到底部。每个新条目只是一长串文本,每个条目由换行符分隔。我尝试了一个更改处理程序,它将 setscrolltop 设置为 Double.MIN_VALUE 但无济于事。关于如何做到这一点的任何想法?

原文由 Sam Keays 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

我没有足够的声誉来发表评论,但想为未来的读者提供一些见解,说明为什么 setText 似乎没有触发侦听器,但 appendText 确实如此,就像 Math 的回答一样。

我自己遇到类似问题时刚刚找到了这个答案,并查看了代码。这是目前在谷歌搜索中“javafx textarea settext scroll”的最高结果。

setText 确实会触发侦听器。根据 TextInputControl(TextArea 的超类)中 doSet 方法的 javadoc:

>       * doSet is called whenever the setText() method was called directly
>      * on the TextInputControl, or when the text property was bound,
>      * unbound, or reacted to a binding invalidation. It is *not* called
>      * when modifications to the content happened indirectly, such as
>      * through the replaceText / replaceSelection methods.
>
> ```

在 doSet 方法中,调用了 updateText(),TextArea 覆盖了它:

@Override final void textUpdated() { setScrollTop(0); setScrollLeft(0); }

”`

因此,当您像 Math 的答案那样在侦听器中设置滚动量时,会发生以下情况:

  1. TextProperty 已更新
  2. 你的听众被调用,滚动被设置
  3. doSet 被称为
  4. 调用 textUpdated
  5. 滚动条设置回左上角

然后当您附加“”时,

  1. TextProperty 已更新
  2. 你的听众被调用,滚动被设置

上面的 javadoc 很清楚为什么会这样——doSet 仅在使用 setText 时被调用。事实上,appendText 调用 insertText,而 insertText 调用 replaceText - javadoc 进一步声明 replaceText 不会触发对 doSet 的调用。

这种行为相当令人恼火,尤其是因为这些都是最终方法,乍一看并不明显 - 但不是错误。

原文由 Matthew 发布,翻译遵循 CC BY-SA 4.0 许可协议

您必须向 TextArea 元素添加一个侦听器,以便在其值更改时滚动到底部:

 @FXML private TextArea txa;

...

txa.textProperty().addListener(new ChangeListener<Object>() {
    @Override
    public void changed(ObservableValue<?> observable, Object oldValue,
            Object newValue) {
        txa.setScrollTop(Double.MAX_VALUE); //this will scroll to the bottom
        //use Double.MIN_VALUE to scroll to the top
    }
});

但是当您使用 setText(text) 方法时不会触发此侦听器,因此如果您想在 setText(text) 之后触发它,请使用 appendText(text) :—c67ad65

 txa.setText("Text into the textArea"); //does not trigger the listener
txa.appendText("");  //this will trigger the listener and will scroll the
                     //TextArea to the bottom

这听起来更像是一个错误,一旦 setText() 应该触发 changed 侦听器,但它没有。这是我自己使用的解决方法,希望对您有所帮助。

原文由 Math 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题