Using GridPane for a complex layout of controls in our application I found some odd behaviour surrounding VPos.BASELINE alignment set on all row constraints in the grid.
Firstly using baseline alignment with an hgap and/or a vgap set sometimes causes an extra gap at the outside of the grid.
Secondly turning on grid lines totally messes up the layout of nodes in the grid.
Run the following test case.
At first everything is nicely lined up. Click on the "Grid Lines" button and you will see with the grid lines visible that there is actually an extra vgap at the bottom. Then, anything that will cause the grid to re-layout will seem to re-position the first row in totally the wrong place (like resizing the stage).
Finally, you can select the "Default Row Align" checkbox to see the odd behaviours disappear once the row constraints are removed.
*******************************************************************
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class GridPaneTest extends Application {
@Override public void start(final Stage primaryStage) throws Exception {
final GridPane grid = new GridPane();
grid.setHgap(20);
grid.setVgap(20);
RowConstraints rc = new RowConstraints();
rc.setValignment(VPos.BASELINE);
ChoiceBox<String> comboBox = new ChoiceBox<>(
FXCollections.observableArrayList("Short", "Longer", "Really Long"));
comboBox.getSelectionModel().select(0);
grid.getRowConstraints().add(rc);
grid.add(new BaseHBox(new Label("test1: "), comboBox), 0, 0);
rc = new RowConstraints();
rc.setValignment(VPos.BASELINE);
grid.getRowConstraints().add(rc);
grid.add(new BaseHBox(new Label("test2: "), new Button("Grid Lines") {
{setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(ActionEvent event) {
grid.setGridLinesVisible(!grid.isGridLinesVisible());
}
});}
}), 0, 1);
rc = new RowConstraints();
rc.setValignment(VPos.BASELINE);
grid.getRowConstraints().add(rc);
grid.add(new BaseHBox(new Label("test3: "), new TextField("testing...") {
{setPrefColumnCount(6);}
}), 0, 2);
rc = new RowConstraints();
rc.setValignment(VPos.BASELINE);
grid.getRowConstraints().add(rc);
ToggleGroup tGroup = new ToggleGroup();
RadioButton radio1 = new RadioButton("Choice 1");
RadioButton radio2 = new RadioButton("Choice 2");
radio1.setToggleGroup(tGroup);
radio2.setToggleGroup(tGroup);
grid.add(new BaseHBox(new Label("test4: "),
new VBox(5, radio1, radio2)), 1, 0);
grid.add(new BaseHBox(new Label("test5: "), new CheckBox("Default Row Align") {
{final List<RowConstraints> constraints = new ArrayList<>();
selectedProperty().addListener(new InvalidationListener() {
@Override public void invalidated(Observable observable) {
if ( isSelected() ) {
constraints.addAll(grid.getRowConstraints());
grid.getRowConstraints().clear();
} else {
grid.getRowConstraints().addAll(constraints);
constraints.clear();
}
}});}
}), 1, 1);
CheckBox mainCheck = new CheckBox("Main choice");
CheckBox subCheck = new CheckBox("Sub choice");
subCheck.disableProperty().bind(Bindings.not(mainCheck.selectedProperty()));
VBox.setMargin(subCheck, new Insets(0, 0, 0, 20));
grid.add(new BaseHBox(new Label("test6: "),new VBox(5, mainCheck, subCheck)), 1, 2);
primaryStage.setScene( new Scene(grid) );
primaryStage.sizeToScene();
primaryStage.centerOnScreen();
primaryStage.show();
}
public static void main(String[] args) throws Exception{
launch(args);
}
private static class BaseHBox extends HBox {
public BaseHBox(Node ... nodes) {
super(5, nodes);
setAlignment(Pos.BASELINE_LEFT);
}
}
}