JavaFX - Adding nodes to ScrollPane with correct scrolling direction

CAG Gonzo picture CAG Gonzo · Aug 7, 2013 · Viewed 14k times · Source

I have a ScrollPane in my scene and would like to add a series of Nodes to it. The exact amount must be dynamic. I've been testing the concept with Label nodes and can successfully add as many Labels as I want to the content of the ScrollPane (currently a VBox).

My problem is figuring out how to allow the user to scroll normally through the ScrollPane full of Nodes. The content matches pace with the scrollbar; that is, when I scroll down, the content moves down. I scroll up, the content scrolls up. So if I have 10 Labels, only five of which are currently visible, the instinctive action to see the other five would be to scroll down. Unfortunately, this just moves the entire content down, exposing empty space up top and hiding more of the Labels.

I can post some sample code if that helps, but the gist of my plan of attack is this:

ScrollPane sp = new ScrollPane();
VBox content = new VBox();
sp.setContent(content);
for (int i = 0; i < 10; i++)
{
    Label label = new Label("Label " + i);
    content.setPrefHeight(content.getPrefHeight() + label.getPrefHeight());
    content.getChildren().add(label);
}

Because I use a VBox, the Labels are stacked (in the Y axis) atop one another, which is what I want. As more Labels are added, the ScrollBar needs to reflect the increased size of the VBox. I've tried a few approaches to get this to work, including ScrollPane.setVmax() method, which is ok, but I still have the issue of the scroll direction moving the content in the wrong direction. I've also tried an EventHandler and EventFilter to modify values accordingly, still without solving the problem of scrolls not moving the content in the right direction.

The answer seems so simple, yet the it continues to evade me, even after many long hours messing around with the code.

EDIT:

jewelsea's suggestion of using a ListView solved my problem. However, I remain curious as to why using a ScrollPane did not fare so well. Additionally, I've run into odd behavior with the ListView implementation: I use a button to manually add a new Label to the view. Every now and then, the view will freeze up after adding a new Label. It locks up for a few seconds before either updating the scroll position or displaying the newly added Label. I don't know if this is because there are about 20 or so Label instances being managed by the view or if something more insidious is at play.

Answer

Brendan picture Brendan · Aug 9, 2013

In regards to the scrollpane issues, I know what you're looking to do is possible because I'm doing something very similar. Based on the code snippet you gave above I would suggest trying few things...

  • Give the ScrollPane a preferred height and width to follow.
  • Don't give the content VBox any height sizing preference as it will grow with its contents. There should be no need to update its height after adding content either.
  • Use the VBox's setAlignment method to align its contents either TOP_LEFT, TOP_CENTER, or TOP_RIGHT.
  • Be cautious when using the getPrefHeight() method because if you haven't used setPrefHeight() beforehand I believe it will return -1.

Hope this helps you out!