Can I force JavaFX's GridPane to distribute space evenly?
Asked Answered
W

1

7

I'm facing a bit of weird layout behaviour when using GirdPanes in JavaFX 2. While it usually seems to spread horizontal space evenly between multiple fields, it doesn't do so in some other cases. Here is an example showing the effect:

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class TestDialog extends Stage {
    public TestDialog() {
        super();
        setTitle("Test");

        GridPane grid = new GridPane();
        grid.setHgap(5);
        grid.setVgap(5);
        grid.setPadding(new Insets(10, 10, 10, 10));

        final TextField tField1 = new TextField();
        final TextField tField2 = new TextField();
        tField2.setMaxWidth(200);

        grid.add(createLabel("Field 1:"), 0, 0);
        grid.add(tField1, 1, 0);
        grid.add(createLabel("Field 2:"), 2, 0);
        grid.add(tField2, 3, 0);

        Pane pane = new Pane();
//        pane.setMinSize(600, 100);  // first row has weird layout behaviour
        pane.setMinSize(100, 100); // first row is fine
        pane.setStyle("-fx-background-color: black");
        grid.add(pane, 0, 1, 4, 1);

        grid.setMinSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);

        setScene(new Scene(grid));
    }

    private Label createLabel(String text) {
        Label label = new Label(text);
        label.setMinSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);
        return label;
    }

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

    public static class TestApplication extends Application {
        @Override
        public void start(Stage stage) throws Exception {
            TestDialog dialog = new TestDialog();
            dialog.showAndWait();
        }

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

In this example the dialog will resize nicely if run as is. If the minimum size of the extra Pane is changed to the version in the comment, then things start going wrong: extra space in the first row will be turned into an empty space (instead of growing the first field), reducing the dialog size takes it away from the already small first field, leaving the empty area intact.

Is there a way to get GridPane to actually use the available horizontal space for the first field? I understand that reducing the dialog size below the minimum needed doesn't necessarily product good results, but not expanding the field in the first place seems plain wrong to me.

I'm using JavaFX as of JDK 1.7.0_21.

Wraf answered 1/5, 2013 at 1:10 Comment(0)
S
3

You'll have to look into the ColumnConstraints and RowConstraints classes. These will tell a GridPane how to distribute space. Unfortunately, the API is more than a little awkward here. If you want to evenly distribute an unknown amount of space, you'll have to first instanciate a constraint, then use #setPercentageWidth - this option is not available in the constructor.

All in all, a GridPane with 3 evenly distributed columns (if possible while respecting min sizes) will look like this:

public class Test extends Application {
    public void start(final Stage stage) throws Exception {
        final GridPane grid = new GridPane();
        grid.getColumnConstraints().setAll(
                ColumnConstraintsBuilder.create().percentWidth(100/3.0).build(),
                ColumnConstraintsBuilder.create().percentWidth(100/3.0).build(),
                ColumnConstraintsBuilder.create().percentWidth(100/3.0).build()
        );
        grid.add(new Button("One"),0,0);
        grid.add(new Button("Two"),1,0);
        grid.add(new Button("and three"),2,0);

        stage.setScene(new Scene(grid));
        stage.show();
    }

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

You can handle RowConstraints accordingly. You may also want to set the alignment in the cells to make sure your dialog still looks good when resizing it.

Slate answered 1/5, 2013 at 16:16 Comment(2)
I am aware of the constraints, but so far my experiments all produced interesting, but not very useful results. The calculation of the widths seems utterly broken in the context of minimum sizes present - if all columns are set to 25% wide the window gets huge. I've moved on to MiG Layout by now.Wraf
ColumnConstraintsBuilder is deprecated. See ColumnConstraints instead.Metaprotein

© 2022 - 2024 — McMap. All rights reserved.