JavaFX自动滚动下滚动面板

5

当ScrollPane内容的高度增加时,有没有自动向下滚动ScrollPane控件的方法? 例如,我在屏幕底部(在ScrollPane内部)有一个TitledPane,当我展开它时,我希望ScrollPane向下滚动,这样我就可以看到整个TitledPane的内容。

8个回答

19

你可以使用bind方法将ScrollPanevvalue属性与内部容器的heightProperty绑定。例如,如果你在ScrollPane中有一个VBox

scrollPane.vvalueProperty().bind(vBox.heightProperty());

哇...这个解决方案对我很有效。但是,你能再解释一下吗? - Fadhil Ahmad
它将隐藏顶部的标题面板。 - Ari
这应该被视为不良实践,原因如下: vvalue(垂直值)表示滚动条的垂直位置,以百分点表示(如其他评论中所述),范围从0到1(双倍) VBoxheight(也是双倍)将大于1,因为您很可能没有高度小于像素的容器 这会导致将大值设置为滚动条位置 我认为这能够工作是因为如果vvalue大于1,则将其视为1 - gkhaos

3

我也遇到了同样的问题,尝试了答案中的多种方法。 我的问题是ScrollPane内容被其他线程使用Platform.runLater()更新,如果更新很快,之前的所有方法都不够好。 对于所有遇到此类问题的人,你可以简单地使用以下方法:

ScrollPane scrollPane = new ScrollPane();
scrollPane.needsLayoutProperty().addListener((observable, oldValue, newValue) -> {
    if (!newValue) {
        scrollPane.setVvalue(1.0);
    }
});

2
您可以像这样将侦听器添加到TitledPane的高度属性中:
titledPane.heightProperty().addListener((observable, oldValue, newValue) -> 
       vvalueProperty().set(newValue.doubleValue()));

2

在向垂直或水平滚动条传递值之前,您必须告诉scrollpane当前坐标的位置。

这段代码对我来说非常有效:

// 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 ); 
    }
);

就是这样了!


2
你可以通过结合使用 titledPane.localToScene()scrollPane.setVvalue() 来实现这种行为。
第一个是获取titledPane的坐标,而第二个是设置scrollPane的垂直滚动条位置。请注意,它的范围在0-1之间。

我有一个类似的问题。我需要上下移动titledpane。我该怎么做?主要我想实现IntelliJ输出窗口的功能。那个窗口可以用鼠标上下移动。 - alhelal

0

innerPane.widthProperty().addListener((observable, oldValue, newValue) -> { scrollPane.setHvalue(1.0d); });

如果您尝试通过监听innerPane的子列表更改来更改滚动条位置,则不起作用,因为此更改在此时尚未与innerPane布局一起计算。因此,您必须注意宽度或高度属性!


0

不知道它是否仍然相关,我曾经遇到过类似的问题,这个解决方案对我有效。我需要在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);

我知道这段代码并不是很具有代表性,但如果有人需要实现的更多细节,我可以详细说明...


-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();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接