JavaFX TextArea和autoscroll

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

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

 @FXML private TextArea txa; ... txa.textProperty().addListener(new ChangeListener() { @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)

 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侦听器,这听起来更像是一个bug,但事实并非如此。 这是我自己使用的解决方法,希望它对您有所帮助。

txa.appendText(“”)将在没有监听器的情况下滚动到底部 。 如果要向后滚动并且文本不断更新,这将成为一个问题。 txa.setText(“”)将滚动条放回顶部并应用相同的问题。

我的解决方案是扩展TextArea类,将textML的FXML标记修改为LogTextArea。 如果这有效,它显然会导致场景构建器出现问题,因为它不知道这个组件是什么

 import javafx.scene.control.TextArea; import javafx.scene.text.Font; public class LogTextArea extends TextArea { private boolean pausedScroll = false; private double scrollPosition = 0; public LogTextArea() { super(); } public void setMessage(String data) { if (pausedScroll) { scrollPosition = this.getScrollTop(); this.setText(data); this.setScrollTop(scrollPosition); } else { this.setText(data); this.setScrollTop(Double.MAX_VALUE); } } public void pauseScroll(Boolean pause) { pausedScroll = pause; } } 

替代那个奇怪的setText错误而不使用appendText

 textArea.selectPositionCaret(textArea.getLength()); textArea.deselect(); //removes the highlighting 

我要添加到jamesarbrown的响应的一个附录是,这将是使用布尔属性,因此您可以从FXML中访问它。 像这样的东西。

 import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.scene.control.TextArea; public class LogTextArea extends TextArea { private final BooleanProperty pausedScrollProperty = new SimpleBooleanProperty(false); private double scrollPosition = 0; public LogTextArea() { super(); } public void setMessage(String data) { if (isPausedScroll()) { scrollPosition = this.getScrollTop(); this.setText(data); this.setScrollTop(scrollPosition); } else { this.setText(data); this.setScrollTop(Double.MAX_VALUE); } } public final BooleanProperty pausedScrollProperty() { return pausedScrollProperty; } public final boolean isPausedScroll() { return pausedScrollProperty.getValue(); } public final void setPausedScroll(boolean value) { pausedScrollProperty.setValue(value); } } 

但是,这个答案的问题在于,如果你被大量输入淹没(从IO流中检索日志时会发生这种情况),javaFX线程将锁定,因为TextArea获取了太多数据。