JavaFX SplitPane dynamically resize children

108 Views Asked by At

I have a SplitPane and within it two items which are VBox and ScrollPane. In the VBox I have some TitledPane children that can be collapsed and therefore minimize the VBox height, or this is what I thought will happen. But the issue is that only the inner elements of the VBox are being shrunk inside it and the actual VBox child height stays the same.

I want the VBox to dynamically change in height and the divider of the SplitPane to automatically fill the gap of the shrunk VBox so that the ScrollPane will fill that gap.

<SplitPane fx:id="infoSplitPane" orientation="VERTICAL" dividerPositions="0.35">
    <items>
        <VBox fx:id="campaignInfoVBox" spacing="10" VBox.vgrow="ALWAYS">
            <children>
                <Label text="Campaign Information" style="-fx-font-size: 120%" />                                         
                <SplitPane fx:id="campaignInfoSplitPane" orientation="VERTICAL">
                    <items>
                        <TitledPane fx:id="campaignTestsFlow" text="Campaign Tests Flow">
                            <TableView fx:id="testCasesTableView" minHeight="52" maxHeight="Infinity" VBox.vgrow="ALWAYS">
                                <columnResizePolicy>
                                    <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
                                </columnResizePolicy>
                            </TableView>
                        </TitledPane>
                        <TitledPane fx:id="campaignActionsInfo" text="Campaign Actions Information">
                            <SplitPane fx:id="campaignTablesSplitPane" orientation="VERTICAL" VBox.vgrow="ALWAYS">
                                <items>
                                    <RunnerActionsTreeTableView fx:id="campaignSetupTable" name="Campaign Setup" VBox.vgrow="SOMETIMES" />
                                    <RunnerActionsTreeTableView fx:id="campaignTearDownTable" name="Campaign Tear Down" VBox.vgrow="ALWAYS" />
                                </items>
                            </SplitPane>
                        </TitledPane>
                    </items>
                </SplitPane>
            </children>
        </VBox>
        <ScrollPane fx:id="testInfoScrollPane" fitToWidth="true" VBox.vgrow="ALWAYS">
            <content>
                <VBox spacing="0" VBox.vgrow="ALWAYS">
                    <GridPane hgap="5.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="0.0" minWidth="0.0" vgap="5.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="0.0">
                        <children>                                                                                    
                            <VBox fx:id="titledPaneVbox"  GridPane.rowIndex="13" GridPane.columnSpan="2">
                                <TitledPane fx:id="variablesTitlePane" maxHeight="1.7976931348623157E308" text="Variables Information" VBox.vgrow="ALWAYS" >
                                    <content>
                                        <TableView fx:id="variablesTable" maxHeight="Infinity" maxWidth="Infinity"  GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS"  />
                                    </content>
                                </TitledPane>
                                <TitledPane fx:id="eventsTitlePane" maxHeight="1.7976931348623157E308" text="Events Information" VBox.vgrow="ALWAYS"  GridPane.columnSpan="2">
                                    <content>
                                        <TableView fx:id="eventsTable" maxHeight="Infinity" maxWidth="Infinity" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS"/>
                                    </content>
                                </TitledPane>
                            </VBox>
                            <Button fx:id="testCaseDirButton" text="Logs Folder" maxWidth="Infinity" GridPane.rowIndex="14" GridPane.hgrow="ALWAYS" GridPane.columnSpan="2" />
                        </children>
                    </GridPane>
                </VBox>
            </content>
        </ScrollPane>
    </items>
</SplitPane>

So basically what I need it the testInfoScrollPane to adjust itself to campaignInfoVBox bottom margin when it is being shrunk automatically when its TitledPane children are collapsing.

1

There are 1 best solutions below

6
Sai Dandem On

I believe you need to set the maxHeight attribute of VBox to the prefHeight of its contents. That way, the VBox can never grow beyond the size of its contents.

You can try the below code:

If in java code:

campaignInfoVBox.setMaxHeight(Region.USE_PREF_SIZE);

If in FXML code:

<VBox fx:id="campaignInfoVBox" spacing="10" VBox.vgrow="ALWAYS" maxHeight="-Infinity">

Below is a quick demo that demonstrates the fix:

enter image description here

import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class SplitPaneFitContentDemo extends Application {

    @Override
    public void start(final Stage stage) throws Exception {
        StackPane content = new StackPane();
        content.setMinSize(200, 800);
        content.setStyle("-fx-background-color:linear-gradient(to bottom, yellow, red);");
        ScrollPane scrollPane = new ScrollPane(content);

        VBox pane = new VBox();
        // Try setting the below one. In FXML, for the VBox it should have the attribute maxHeight="-Infinity"
        pane.setMaxHeight(Region.USE_PREF_SIZE);
        for (int i = 1; i < 3; i++) {
            VBox tpContent = new VBox(10, new Button("Button A" + i), new Button("Button B" + i));
            TitledPane tp = new TitledPane("Title " + i, tpContent);
            tp.setMaxHeight(Double.POSITIVE_INFINITY);
            VBox.setVgrow(tp, Priority.ALWAYS);
            pane.getChildren().add(tp);
        }

        SplitPane splitPane = new SplitPane(pane, scrollPane);
        splitPane.setOrientation(Orientation.VERTICAL);
        splitPane.setDividerPositions(0.35);

        StackPane root = new StackPane(splitPane);
        Scene scene = new Scene(root, 300, 400);
        stage.setScene(scene);
        stage.setTitle("SplitPane");
        stage.show();
    }
}

UPDATE: When applied the attribute in the provided FXML, this is how it works.

enter image description here