Simon
Simon

Reputation: 87

JavaFX FlowPane within ScrollPane, dynamically adjust scrollpane's content and size

I currently have a ScrollPane with a FlowPane as content. The FlowPane currently initializes with no children nodes, a fixed width and a pref/min height (but no max height).

While adding items to the FlowPane at runtime (I click some UI element and something is added to the FlowPane), the ScrollPane should adjust its height in the case that the addition to the FlowPane no longer fits.

I don't understand how to set the height of the flowPane and ScrollPane so that this works - if that's the problem to begin with. At the moment, whenever the addition to the FlowPane doesn't fit its initial height, the content is added, but not visible. The scrollbar belonging to the ScrollPane never adjusts its height - if it did, I could just scroll further down and see the content.

Let's say I have a ScrollPane with some width and height, some viewport width/height, and a FlowPane with some width/height - What should my settings be for the min/pref/max sizes? How can I make a scrollPane adjust its scrollbar behaviour or make the content visible?

The ScrollPane's setFitToHeight is already set to true, which didn't seem to change anything.

import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class FlowPaneTest extends Application
{

    public static void main(String[] args)
    {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception
    {

        // borderPane rootPane
        BorderPane borderPane = new BorderPane();
        borderPane.setMinSize(600, 600);
        borderPane.setPrefSize(600, 600);
        borderPane.setMaxSize(600, 600);
        // container for the two scrollPanes below
        FlowPane flow = new FlowPane();
        borderPane.setRight(flow);

        // two scrollPanes, each should resize it's height (width should be fixed) if
        // children are added beyond it's current height
        ScrollPane top = new ScrollPane();
        ScrollPane bottom = new ScrollPane();

        FlowPane scrollPaneContent = new FlowPane();
        top.setContent(scrollPaneContent);
        bottom.setContent(scrollPaneContent);

        flow.getChildren().add(top);
        flow.getChildren().add(bottom);

        borderPane.setOnMouseClicked(new EventHandler<Event>()
        {

            @Override
            public void handle(Event event)
            {

                Label l = new Label("test");
                l.setMinSize(100, 100);
                l.setPrefSize(100, 100);
                l.setMaxSize(100, 100);

                scrollPaneContent.getChildren().add(l);

            }
        });

        // size settings

        int width = 300, height = 300;

        top.setHvalue(0.5);

        top.setMinViewportHeight(height);
        top.setPrefViewportHeight(height);
        top.setMinViewportWidth(width);
        top.setPrefViewportWidth(width);
        top.setHbarPolicy(ScrollBarPolicy.ALWAYS);
        top.setFitToHeight(true);

        top.setMinSize(width, height);
        top.setPrefSize(width, height);
        top.setMaxWidth(width);

        scrollPaneContent.setMinSize(width, height);
        scrollPaneContent.setPrefSize(width, height);
        scrollPaneContent.setMaxWidth(width);
        scrollPaneContent.setPrefHeight(height);

        bottom.setMinSize(width, height);
        bottom.setPrefSize(width, height);
        bottom.setMaxWidth(width);
        bottom.setHvalue(0.5);

        bottom.setMinViewportHeight(height);
        bottom.setPrefViewportHeight(height);
        bottom.setMinViewportWidth(width);
        bottom.setPrefViewportWidth(width);
        bottom.setHbarPolicy(ScrollBarPolicy.ALWAYS);
        top.setFitToHeight(true);
        bottom.setFitToHeight(true);

        // stage
        Scene scene = new Scene(borderPane, 600.0, 600.0);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

}

Upvotes: 1

Views: 2167

Answers (2)

Simon
Simon

Reputation: 87

Ending up with something similar to this ugly bit of code - It listens to the number of children in the pane and increases the size every time something is added to the list of children:

topSubPane.getChildren().addListener(new ListChangeListener()
    {

        @Override
        public void onChanged(Change c)
        {
            c.next();

            topSubPane.setPrefHeight(topSubPane.getHeight() + 50);

        }
    });

Works, but feels like an unorthodox hack. Is there really no regular way of doing this?

Upvotes: 1

Ahmed Emad
Ahmed Emad

Reputation: 674

Try to give the ScrollPane pref height and width and add this line

scrollPane.setFitToWidth(true);

Upvotes: 0

Related Questions