JavaFXTextArea和autoscroll
我试图获得一个文本区域,通过事件处理程序将新文本自动滚动到底部。每个新条目只是一个长文本字符串,每个条目之间用换行符分隔。我尝试了一个将setscrolltop设置为Double.MIN_值的更改处理程序,但没有效果。您知道如何做到这一点吗?您必须在JavaFXTextArea和autoscroll,java,javafx-2,Java,Javafx 2,我试图获得一个文本区域,通过事件处理程序将新文本自动滚动到底部。每个新条目只是一个长文本字符串,每个条目之间用换行符分隔。我尝试了一个将setscrolltop设置为Double.MIN_值的更改处理程序,但没有效果。您知道如何做到这一点吗?您必须在TextArea元素中添加一个侦听器,以便在其值更改时滚动到底部: @FXML private TextArea txa; ... txa.textProperty().addListener(new ChangeListener<Obj
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
}
});
这听起来更像是一个bug,一旦setText()
应该触发changed
监听器,但是它不会。这是我自己使用的解决方法,希望它能帮助您。txa.appendText(“”)将在没有侦听器的情况下滚动到底部。如果您想向后滚动并且文本不断更新,这将成为一个问题。setText(“”)将滚动条放回顶部,同样的问题也适用
我的解决方案是扩展TextArea类,将FXML标记从TextArea扩展到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;
}
}
不使用appendText的奇怪setText错误的替代方法
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获取了太多的数据。我没有足够的声誉发表评论,但是我想给未来的读者一些启示,为什么setText看起来不会触发听者,而appendText会触发听者,就像Math的答案一样 我只是在自己遇到类似问题时找到了这个答案,并研究了代码。这是目前谷歌搜索中“javafx textarea settext scroll”的最高结果 setText确实会触发侦听器。 根据TextInputControl(TextArea的超类)中doSet方法上的javadoc: 在doSet方法中,对updateText()进行了调用,其中TextArea覆盖:
@Override final void textUpdated() {
setScrollTop(0);
setScrollLeft(0);
}
因此,当您将侦听器中的滚动量设置为Math的答案时,会发生以下情况:
这种行为相当令人恼火,特别是因为这些都是最终的方法,乍一看并不明显,但不是一个bug。
setScrollTop(Double.MIN_值)代码>滚动到顶部,而MAX_VALUE
滚动到底部。@AdamJensen我在这里做一个测试,因为我不久前回答了这个问题,只是看了不记得了。谢谢你的报告。@AdamJensen你完全正确。我刚修好。谢谢我建议在Platform.runLater()中设置滚动条——我的文本区域有时会错过一些没有滚动条的滚动条更新。我似乎无法让它工作,我的文本区域只是一直滚动到顶部。有什么想法吗?两者都使用Platform.runLater(()->this.setScrollTop(Double.MAX_值))代码>或设置Crolltop(双最大值)
。此外,我的文本区域似乎很模糊。
* 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.
@Override final void textUpdated() {
setScrollTop(0);
setScrollLeft(0);
}