Is there any way of auto scroll down a ScrollPane control when it content's height increases ? For example, I have a TitledPane on the bottom of the screen (inside a ScrollPane) and when I expand it I would like the ScrollPane to scroll down so I can see the entire content of the TitledPane.
8 Answers
You can bind
the ScrollPane
vvalue
property with the heightProperty
of the inner container. For example, if you have a VBox
in your ScrollPane
:
scrollPane.vvalueProperty().bind(vBox.heightProperty());

- 814
- 13
- 33
-
Wow... this solution works for me. but, can you explain more? – Fadhil Ahmad Aug 02 '17 at 03:25
-
it will hides the top titledpane. – Ari Aug 09 '17 at 01:21
-
this should be considered bad practice, here's why: The `vvalue` (for vertical value, which means the vertical position of the scroller in percent points (as stated out in other comments) ranging from 0 (double) the `height` (also a double) of a `VBox` will be larger than 1, as you most-likely will not have a Container with height of less than a pixel this results in a large value set to the scroller position I assume this works because the `vvalue` is treated as 1 if it's larger than 1 – gkhaos Oct 08 '20 at 14:49
I had the same problem and I tried more than one of the approaches in the answers.
My problem was that the ScrollPane
contents are being updated from other threads using Platform.runLater()
, and if the update is very fast all previous methods were not good enough.
For all who face such issue you can simply use this:
ScrollPane scrollPane = new ScrollPane();
scrollPane.needsLayoutProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue) {
scrollPane.setVvalue(1.0);
}
});

- 31
- 1
You can achieve that behaviour With combination of titledPane.localToScene()
and scrollPane.setVvalue()
The first is to get titledPane's coordinates while the second is to set scrollPane's vertical bar position. Note that it's range is between 0 - 1.

- 1,388
- 11
- 14
-
I have about a similar problem. I need to move up/down the titledpane. How can I do? Mainly I wan to implement the IntelliJ output window features. That window can be moved up/down with mouse. – alhelal Oct 29 '17 at 16:05
You have to tell scrollpane where is the current coordinates before pass a value to the vertical or horizontal bar.
This code works pretty fine for me:
// 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 );
You have to code this where your scrollpane grows. For example, if you add nodes to the scrollpane inner node, them, add a listener to it's children list.
If the inner node of scrollpane change it's height, add a listener to the heightProperty.
For example, the inner node of your scrollPane it's an AnchorPane and you add nodes to this pane, so do like this:
anchorPane.getChildren().addListener(
( ListChangeListener.Change<? extends Node> c ) -> {
titledPane.layout();
scrollPane.setVvalue( 1.0d );
}
);
If it's the height which grows...
heightProperty().addListener(
(observable, oldValue, newValue) -> {
titledPane.layout();
scrollPane.setVvalue( 1.0d );
}
);
That's it!

- 43,537
- 11
- 94
- 122

- 321
- 4
- 16
You can add a listener to the TitledPane's height property like that:
titledPane.heightProperty().addListener((observable, oldValue, newValue) ->
vvalueProperty().set(newValue.doubleValue()));

- 31
- 4
Donno if it is still relevant, I have had a similar issue-ish and this solution worked for me. I needed the scrollbar to auto scroll in an MVVM pattern. What I did was to bind the textarea's scrollTopProperty in the View with a SimpleDoubleProperty in the ViewModel. The only issue is that the scrollTopProperty, basically scrolls based on pixel so I increased it based on the number of lanes * 100;
View
textArea.textProperty().bindBidirectional(viewModel.SimpleStringProperty());
textArea.scrollTopProperty().bindBidirectional(viewModel.SimpleDoubleProperty());
ViewModel
SimpleDoubleProperty.setValue(SimpleStringProperty.getValue().split("\n").length * 100);
I know that the code is not really representative, but if someone needs more details of the implementations I can elaborate...

- 307
- 2
- 18
innerPane.widthProperty().addListener((observable, oldValue, newValue) -> { scrollPane.setHvalue(1.0d); });
If you try to change the scrollbars position by listening to changes of the innerPane's childlist does not work because this change has not yet been calculated with the innerPane layout at this moment. Therefore you have to pay attention to the property width or height!

- 11
- 2
I did it by using an AnimationTimer. I had to wait for 100000000 nanoseconds to be sure that the ScrollPane had reacted to the expanded 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();
}