JavaFX TextArea和autoscroll
我试图让TextArea自动滚动到底部,新文本通过事件处理程序放入。 每个新条目只是一个长字符串,每个条目用换行符分隔。 我已经尝试了一个更改处理程序,它将setscrolltop设置为Double.MIN_VALUE,但无济于事。 有关如何做到这一点的任何想法?
您必须向TextArea
元素添加一个侦听器,以便在更改其值时滚动到底部:
@FXML private TextArea txa; ... txa.textProperty().addListener(new ChangeListener
但是当你使用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获取了太多数据。