Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 375
Peter Becker Avatar asked May 01 '13 01:05

Peter Becker


People also ask

How do I center align text in JavaFX?

If you haven't given any value for this property, by default, the length longest line in the text is considered as the width of the bounding box. CENTER − Aligns the text in the center of the bounding box. JUSTIFY − Justifies the text alignment within the bounding box. LEFT − Aligns the text to the left.

How the nodes in a grid pane are arranged?

If we use Grid Pane in our application, all the nodes that are added to it are arranged in a way that they form a grid of rows and columns. This layout comes handy while creating forms using JavaFX.

How do I increase the size of the GridPane in JavaFX?

getColumnConstraints(). add(new ColumnConstraints(200)); By default the GridPane will resize rows/columns to their preferred sizes even if the gridpane is resized larger than its preferred size. To support dynamic column/row sizes, both contstaints class provides three property: min size, max size and preferred size.


1 Answers

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.

like image 134
sarcan Avatar answered Oct 05 '22 12:10

sarcan