【发布时间】:2012-10-20 20:22:57
【问题描述】:
当 ScrollPane 控件的内容高度增加时,有没有办法自动向下滚动? 例如,我在屏幕底部(在 ScrollPane 内)有一个 TitledPane,当我展开它时,我希望 ScrollPane 向下滚动,这样我就可以看到 TitledPane 的全部内容。
【问题讨论】:
当 ScrollPane 控件的内容高度增加时,有没有办法自动向下滚动? 例如,我在屏幕底部(在 ScrollPane 内)有一个 TitledPane,当我展开它时,我希望 ScrollPane 向下滚动,这样我就可以看到 TitledPane 的全部内容。
【问题讨论】:
您可以通过结合使用 titledPane.localToScene() 和 scrollPane.setVvalue() 来实现该行为
第一个是获取titledPane的坐标,第二个是设置scrollPane的垂直条位置。请注意,它的范围在 0 - 1 之间。
【讨论】:
我是通过使用 AnimationTimer 来实现的。我必须等待 100000000 纳秒才能确保 ScrollPane 已对扩展的 Titlepane 做出反应。
public void scrollNodeInTopScrollPane(Node n, ScrollPane s) {
final Node node = n;
final ScrollPane clientTopScrollPane = s;
AnimationTimer timer = new AnimationTimer() {
long lng = 0;
@Override
public void handle(long l) {
if (lng == 0) {
lng = l;
}
if (l > lng + 100000000) {
if (node.getLocalToSceneTransform().getTy() > 20) {
clientTopScrollPane.setVvalue(clientTopScrollPane.getVvalue() + 0.05);
if (clientTopScrollPane.getVvalue() == 1) {
this.stop();
}
} else {
this.stop();
}
}
}
};
timer.start();
}
【讨论】:
在将值传递给垂直或水平条之前,您必须告诉滚动窗格当前坐标在哪里。
这段代码对我来说很好用:
// the owner's node of your scrollPane;
titledPane.layout();
// the maxValue for scrollPane bar ( 1.0 it's the default value )
scrollPane.setVvalue( 1.0d );
您必须在滚动窗格增长的地方对此进行编码。例如,如果您将节点添加到滚动窗格内部节点,则它们会在其子列表中添加一个侦听器。
如果滚动窗格的内部节点改变了它的高度,给heightProperty添加一个监听器。
例如,你的 scrollPane 的内部节点是一个 AnchorPane 并且你将节点添加到这个窗格中,所以这样做:
anchorPane.getChildren().addListener(
( ListChangeListener.Change<? extends Node> c ) -> {
titledPane.layout();
scrollPane.setVvalue( 1.0d );
}
);
如果是身高增长的话……
heightProperty().addListener(
(observable, oldValue, newValue) -> {
titledPane.layout();
scrollPane.setVvalue( 1.0d );
}
);
就是这样!
【讨论】:
您可以将bindScrollPanevvalue 属性与内部容器的heightProperty 结合使用。例如,如果您的ScrollPane 中有VBox:
scrollPane.vvalueProperty().bind(vBox.heightProperty());
【讨论】:
vvalue(用于垂直值,这意味着滚动条的垂直位置以百分比为单位(如其他 cmets 中所述)范围从 0 ( double) VBox 的 height (也是 double) 将大于 1,因为您很可能没有高度小于像素的 Container 这会导致将较大的值设置为滚动条位置我认为这是可行的,因为如果 vvalue 大于 1,则将其视为 1
您可以像这样向 TitledPane 的高度属性添加一个侦听器:
titledPane.heightProperty().addListener((observable, oldValue, newValue) ->
vvalueProperty().set(newValue.doubleValue()));
【讨论】:
Donno,如果它仍然相关,我遇到了类似的问题,这个解决方案对我有用。我需要滚动条以 MVVM 模式自动滚动。我所做的是将视图中 textarea 的 scrollTopProperty 与 ViewModel 中的 SimpleDoubleProperty 绑定。唯一的问题是 scrollTopProperty,基本上是基于像素滚动的,所以我根据车道数 * 100 增加了它;
查看
textArea.textProperty().bindBidirectional(viewModel.SimpleStringProperty());
textArea.scrollTopProperty().bindBidirectional(viewModel.SimpleDoubleProperty());
视图模型
SimpleDoubleProperty.setValue(SimpleStringProperty.getValue().split("\n").length * 100);
我知道代码并没有真正的代表性,但是如果有人需要更多的实现细节,我可以详细说明...
【讨论】:
innerPane.widthProperty().addListener((observable, oldValue, newValue) -> { scrollPane.setHvalue(1.0d); });
如果您尝试通过监听 innerPane 子列表的更改来更改滚动条位置,则不起作用,因为此时尚未使用 innerPane 布局计算此更改。因此,您必须注意属性的宽度或高度!
【讨论】:
我遇到了同样的问题,我在答案中尝试了不止一种方法。
我的问题是ScrollPane 内容正在使用Platform.runLater() 从其他线程更新,如果更新非常快,所有以前的方法都不够好。
对于所有面临此类问题的人,您可以简单地使用:
ScrollPane scrollPane = new ScrollPane();
scrollPane.needsLayoutProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue) {
scrollPane.setVvalue(1.0);
}
});
【讨论】: