javajavafxfxmlpane

JavaFX: How to make a VBox and it's contents expand infinitely with window height like they do with width?


Probably a very simple question but I have not been able to figure it out.

I have a ScrollPane (feat. Label) inside a VBox, inside a SplitPane:

(Full fxml file at the bottom)

enter image description here

When you expand the window or the split pane seperator horizontally, the Vbox automatically stretches to fit, the label re-centers appropriatelly, and the scroll pane expands to fit the vbox. This does not happen when epxanding vertically, and I would like it to. How can I achieve that? If there is a different container I should be using instead, please do tell.

Gif of my troubles if it helps: enter image description here Full fxml file:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>

<AnchorPane prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.java.ui.DefaultLayoutController">
   <children>
      <BorderPane prefHeight="600.0" prefWidth="800.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <top>
            <MenuBar BorderPane.alignment="CENTER">
              <menus>
                <Menu mnemonicParsing="false" text="File">
                  <items>
                    <MenuItem mnemonicParsing="false" text="Close" />
                  </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Edit">
                  <items>
                    <MenuItem mnemonicParsing="false" text="Delete" />
                  </items>
                </Menu>
                <Menu mnemonicParsing="false" text="Help">
                  <items>
                    <MenuItem mnemonicParsing="false" text="About" />
                  </items>
                </Menu>
              </menus>
            </MenuBar>
         </top>
         <center>
            <SplitPane dividerPositions="0.5" prefHeight="160.0" prefWidth="200.0" BorderPane.alignment="CENTER">
              <items>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
                     <children>
                        <VBox prefHeight="573.0" prefWidth="306.0" style="-fx-background-color: #ccbfb1;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
                           <children>
                              <Label alignment="CENTER" maxWidth="Infinity" prefHeight="61.0" prefWidth="260.0" style="-fx-alignment: center; -fx-background-color: #e6d7c8;" text="Text" textAlignment="CENTER">
                                 <font>
                                    <Font name="AdobeDevanagari-Regular" size="51.0" />
                                 </font>
                              </Label>
                              <ScrollPane fx:id="mainScrollPane" prefHeight="559.0" prefWidth="453.0">
                                <content>
                                  <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="200.0" prefWidth="200.0" />
                                </content>
                              </ScrollPane>
                           </children>
                        </VBox>
                     </children>
                  </AnchorPane>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="573.0" prefWidth="364.0">
                     <children>
                        <VBox prefHeight="573.0" prefWidth="396.0" style="-fx-background-color: #e6c896;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                     </children>
                  </AnchorPane>
              </items>
            </SplitPane>
         </center></BorderPane>
   </children>
</AnchorPane>

Solution

  • Original Answer

    Solution: Programatic

    One way you could achieve this is by setting the max height of the VBox and its elements to Double.MAX_VALUE using the setMaxHeight(double) method. Alternatively, you can use the static VBox.setVgrow(Priority) method (the recommended way as far as I'm aware) upon all of the VBox's children. You can iterate over the children just using a regular for loop or forEach stream operation:

    // For loop
    for(Node child : yourBox.getChildren()) {
        VBox.setVgrow(child, Priority.ALWAYS);
    }
    
    // forEach stream operation (Java 8+)
    yourBox.getChildren().forEach(child -> VBox.setVGrow(child, Priorty.ALWAYS));
    

    Edit

    Alternative Solution: Scene Builder

    As helpfully suggested by @Panais, within a JavaFX "Scene Builder" type application such as Gluon, the vgrow attribute for your VBox can be set to Always, allowing the same functionality as above through a simple drop-down menu.

    Alternative Solution: XML

    Also mentioned by this user was the editing of this attribute within XML - setting <VBox prefHeight=..., VBox.vgrow="always" /> within the XML tag for the VBox, achieving the same results as the above 2 answers also.