javalayoutjavafx

Fill width in a Pane


There is a Pane as root and a GridPane as its child. The root resizes with the stage. How can I achieve that the GridPane gets automatically resized with the root to fill the width? Any width should possible. Is it possible without property binding?

This is the situation:

  1. A Pane root (yellow) is the root of the Scene so it fills the width and height of the Stage.
  2. A GridPane (green) with one row and 3 colums as child of root.
  3. The row should have a fixed height.
  4. The first and third column should have a constant size
  5. The middle column should grow to maximum
  6. The GridPane should fill the width of its parent

Unfortunately the GridPane does not fill the width: GridPane should fill the width of its parent

Code:

@Override
public void start(Stage primaryStage) throws Exception {
    // Resizes with the stage
    final Pane root = new Pane();
    root.setStyle("-fx-background-color: yellow");

    // grid: 1 row, 3 colums
    // should have a constant height and should grow in width to fill parent pane
    final GridPane gridPane = new GridPane();
    root.getChildren().add(gridPane);
    gridPane.setStyle("-fx-background-color: green");
    gridPane.setGridLinesVisible(true);

    final RowConstraints row = new RowConstraints(100); // constant height = 100
    final ColumnConstraints col1 = new ColumnConstraints(100, Control.USE_COMPUTED_SIZE, Control.USE_COMPUTED_SIZE);
    // should grow as much as possible in width
    final ColumnConstraints col2 = new ColumnConstraints(200, Control.USE_COMPUTED_SIZE, Double.MAX_VALUE);
    final ColumnConstraints col3 = new ColumnConstraints(100, Control.USE_COMPUTED_SIZE, Control.USE_COMPUTED_SIZE);
    gridPane.getRowConstraints().add(row);
    gridPane.getColumnConstraints().addAll(col1, col2, col3);

    final Scene scene = new Scene(root);
    primaryStage.setScene(scene);
    primaryStage.setWidth(600);
    primaryStage.setHeight(400);
    primaryStage.show();
}

Solution

  • The size of nodes inside panes is controlled by the way the individual pane implements its layout: i.e. the size of a node is effectively determined by its parent. So the overall size of your grid pane is controlled by the layout implementation of Pane.

    Pane actually does minimal layout work: it effectively just positions everything at (0,0) and sizes it to its preferred size. So your grid pane gets its preferred width, which is the sum of the preferred widths of the columns.

    So to get your grid pane to grow, you either need to change its preferred width, or use a layout pane that allows you to control how it grows.

    For example:

    gridPane.prefWidthProperty().bind(root.widthProperty());
    

    will make the grid pane grow to the width of root. This will just add extra space to the right of all three columns, so additionally setting

    col2.setHgrow(Priority.ALWAYS);
    

    will let col2 have the extra width.

    Alternatively, using an AnchorPane for root:

    // Pane root = new Pane();
    AnchorPane root = new AnchorPane();
    

    and setting

    AnchorPane.setLeftAnchor(gridPane, 0.0);
    AnchorPane.setRightAnchor(gridPane, 0.0);
    

    (again with the col2 hgrow set) will have the same effect.

    Or you could do

    VBox root = new VBox();
    root.setFillWidth(true);
    

    (for example: there are many solutions).

    The choice of solution depends on what other nodes, if any, you have inside the root pane.