My goal is to create a GridView that is resizable, always square and contains an equal number of rows and columns, making their cells also square, similar to a Reversi or Chess board.
Here’s a small illustration, the grid is centered horizontally on the content pane.
I’ve tried a multitude of different binding variants and layouts, but I can’t quite get it right. Here’s my controller (so far):
public class Controller { public HBox contentPane; public void initialize() { final int sideLength = 10; final GridPane gridPane = new GridPane(); gridPane.setStyle("-fx-border-color: red; -fx-border-insets: 2"); HBox.setHgrow(gridPane, Priority.ALWAYS); for (int i = 0; i < sideLength; i++) { final ColumnConstraints columnConstraints = new ColumnConstraints(Control.USE_PREF_SIZE, 10, Double.MAX_VALUE); columnConstraints.setHgrow(Priority.ALWAYS); gridPane.getColumnConstraints() .add(columnConstraints); final RowConstraints rowConstraints = new RowConstraints(Control.USE_PREF_SIZE, 10, Double.MAX_VALUE); rowConstraints.setVgrow(Priority.ALWAYS); gridPane.getRowConstraints() .add(rowConstraints); } contentPane.getChildren().add(gridPane); for (int i = 0; i < sideLength; i++) { for (int j = 0; j < sideLength; j++) { final GameCell child = new GameCell(); GridPane.setRowIndex(child, i); GridPane.setColumnIndex(child, j); gridPane.getChildren().add(child); } } } }
And the cells, which are supposed to contain Shapes lates, but I’ve but Circle
s for now just to test it:
public class GameCell extends VBox { private final Circle circle; public GameCell() { circle = new Circle(); setMinSize(0, 0); setPrefSize(Control.USE_COMPUTED_SIZE, Control.USE_COMPUTED_SIZE); getChildren().add(circle); final ChangeListener<Number> listener = (observable, oldValue, newValue) -> circle.setRadius((int) (Math.min(this.getWidth(), this.getHeight()) / 2)); widthProperty().addListener(listener); heightProperty().addListener(listener); } }
This is how it looks currently:
Advertisement
Answer
Solved it with a lot of tinkering, here’s my solution for future reference:
GameCell:
public class GameCell extends Pane { public GameCell() { final Circle circle = new Circle(10); circle.radiusProperty().bind(Bindings.divide(widthProperty(), 4)); circle.centerXProperty().bind(widthProperty().divide(2)); circle.centerYProperty().bind(widthProperty().divide(2)); getChildren().add(circle); } }
GamePane:
public class GamePane extends HBox { public GamePane() { final VBox vBox = new VBox(); vBox.alignmentProperty().set(Pos.CENTER); alignmentProperty().set(Pos.CENTER); final GridPane gridPane = new GridPane(); final NumberBinding binding = Bindings.min(widthProperty(), heightProperty()); gridPane.setMinSize(200, 200); vBox.prefWidthProperty().bind(binding); vBox.prefHeightProperty().bind(binding); vBox.setMaxSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE); vBox.setFillWidth(true); VBox.setVgrow(gridPane, Priority.ALWAYS); final int sideLength = 8; for (int i = 0; i < sideLength; i++) { final ColumnConstraints columnConstraints = new ColumnConstraints(Control.USE_PREF_SIZE, Control.USE_COMPUTED_SIZE, Double.MAX_VALUE); columnConstraints.setHgrow(Priority.SOMETIMES); gridPane.getColumnConstraints().add(columnConstraints); final RowConstraints rowConstraints = new RowConstraints(Control.USE_PREF_SIZE, Control.USE_COMPUTED_SIZE, Double.MAX_VALUE); rowConstraints.setVgrow(Priority.SOMETIMES); gridPane.getRowConstraints().add(rowConstraints); } vBox.getChildren().add(gridPane); getChildren().add(vBox); HBox.setHgrow(this, Priority.ALWAYS); for (int i = 0; i < sideLength; i++) { for (int j = 0; j < sideLength; j++) { final Pane child = new GameCell(); GridPane.setRowIndex(child, i); GridPane.setColumnIndex(child, j); gridPane.getChildren().add(child); } } } }