JavaFX GridPane resizing of pane children

16,039

Is there a way for the GridPanes children to grab vertical and horizontal space at the same time?

Try to use RowConstraints and ColumnConstraints of GridPane:

for (final Button button : dummyButtons()) {
    GridPane.setRowIndex(button, i / (int) nColumns);
    GridPane.setColumnIndex(button, i % (int) nColumns);

    button.setMinSize(MIN_TILE_SIZE, MIN_TILE_SIZE);
    button.setMaxSize(MAX_TILE_SIZE, MAX_TILE_SIZE);

    gridPane.getChildren().add(button);

    i++;
}

for (int j = 0; j < nColumns; j++) {
    ColumnConstraints cc = new ColumnConstraints();
    cc.setHgrow(Priority.ALWAYS);
    gridPane.getColumnConstraints().add(cc);
}

for (int j = 0; j < nRows; j++) {
    RowConstraints rc = new RowConstraints();
    rc.setVgrow(Priority.ALWAYS);
    gridPane.getRowConstraints().add(rc);
}

and without calling addResizeListeners().

Share:
16,039
Georgian
Author by

Georgian

More on me here LinkedIn. Inquiries: [email protected]

Updated on July 21, 2022

Comments

  • Georgian
    Georgian almost 2 years

    This may be a duplicate question, but I haven't found a solution that suits my needs.

    Inspired from jewelsea's ColorChooserSample, half-way through my implementation I realised that manual size can only be set on Controls, and not on Panes. These panes should be smart enough to resize themselves automatically depending on their parent.

    Is there a way for the GridPanes children to grab vertical and horizontal space at the same time? Much like a VBox and HBox combined. I bet the solution involves AnchorPane.

    Keep in my the children are panes and not controls.


    SSCCE with buttons (copy - paste - run - resize window)

    import javafx.application.Application;
    import javafx.beans.property.DoubleProperty;
    import javafx.beans.property.SimpleDoubleProperty;
    import javafx.beans.value.ChangeListener;
    import javafx.beans.value.ObservableValue;
    import javafx.geometry.Bounds;
    import javafx.geometry.Insets;
    import javafx.scene.Node;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.Control;
    import javafx.scene.layout.GridPane;
    import javafx.stage.Stage;
    
    /**
     * 
     * @author ggrec
     *
     */
    public class DashboardFXGrid extends Application
    {
    
        // ==================== 1. Static Fields ========================
    
        private final static double GOLDEN_RATIO = 1.618;
    
        private final static double MIN_TILE_SIZE = 5;
        private final static double MAX_TILE_SIZE = Double.MAX_VALUE;
    
    
        // ====================== 2. Instance Fields =============================
    
        private DoubleProperty prefTileSize = new SimpleDoubleProperty(MIN_TILE_SIZE);
    
        private double nColumns;
        private double nRows;
    
        private GridPane gridPane;
    
    
        // ==================== 3. Static Methods ====================
    
        public static void main(final String[] args)
        {
            Application.launch(args);
        }
    
    
        // ==================== 4. Constructors ====================
    
        @Override
        public void start(final Stage primaryStage) throws Exception
        {
            gridPane = new GridPane();
    
            gridPane.setPadding(new Insets(20));
            gridPane.setHgap(10);
            gridPane.setVgap(10);
    
            nColumns = Math.floor(Math.sqrt(dummyButtons().length) * 2 / GOLDEN_RATIO);
            nRows    = Math.ceil(dummyButtons().length / nColumns);
    
            createContents();
    
            addResizeListeners();
    
            primaryStage.setScene(new Scene(gridPane));
            primaryStage.show();
        }
    
    
        // ==================== 5. Creators ====================
    
        private void createContents()
        {
            int i = 0;
    
            for (final Button button : dummyButtons())
            {
                GridPane.setRowIndex(button,       i / (int) nColumns);
                GridPane.setColumnIndex(button, i % (int) nColumns);
    
                button.setMinSize(MIN_TILE_SIZE, MIN_TILE_SIZE);
                button.setMaxSize(MAX_TILE_SIZE, MAX_TILE_SIZE);
    
                gridPane.getChildren().add(button);
    
                i++;
            }
        }
    
        private void addResizeListeners()
        {
            gridPane.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
    
                @Override public void changed(final ObservableValue<? extends Bounds> observableValue, final Bounds oldBounds, final Bounds newBounds)
                {
                    prefTileSize.set(Math.max(MIN_TILE_SIZE, Math.min(newBounds.getWidth() / nColumns, newBounds.getHeight() / nRows)));
    
                    for (final Node child : gridPane.getChildrenUnmodifiable())
                    {
                        final Control tile = (Control) child;
                        tile.setPrefSize(prefTileSize.get(), prefTileSize.get());
                    }
                }
            });
        }
    
    
        // ==================== 15. Other ====================
    
        private static final Button[] dummyButtons()
        {
            final Button[] buttons = new Button[5];
    
            for(int i = 0; i < buttons.length; i++)
            {
                buttons[i] = new Button(String.valueOf(i));
            }
    
            return buttons;
        }
    
    }
    
  • Georgian
    Georgian about 10 years
    Ok this works with Buttons (Controls). Now how about Panes? They don't have setMinSize and setMaxSize APIs.
  • Uluk Biy
    Uluk Biy about 10 years
    @GGrec Are you sure? Pane has that methods.
  • Georgian
    Georgian about 10 years
    Oh man.. I apologize. You are right, I wrote a dumb comment. Regardless, your answer seems really promising. I'll get back to you.