Один из способов достижения квадрата макета для сетки для любого разрешения вашего окна - это масштабирование, чтобы использовать максимальный размер окна (после некоторого заполнения), сохраняя квадрат размера.
Вместо GridPane
простой Group
более гибкий для перемещения своих детей, хотя для этого требуется ручная компоновка.
Этот простой фрагмент основан на реализации JavaFX игры 2048, вы можете найти here. Он использует узорные прямоугольники для создания сетки, и над ними добавляются «плитки». Чтобы узнать больше о стилизации, макетировании или перемещении плитки, перейдите по ссылке.
private static final int NUM_CELLS = 15;
private static final int CELL_SIZE = 50;
private static final int TILE_SIZE = CELL_SIZE-15;
private final static int MARGIN = 20;
@Override
public void start(Stage primaryStage) {
// create background square grid
Group gridGroup = new Group();
IntStream.range(0,NUM_CELLS).boxed().forEach(i->
IntStream.range(0,NUM_CELLS).boxed().forEach(j->{
Rectangle cell = new Rectangle(i * CELL_SIZE, j * CELL_SIZE, CELL_SIZE, CELL_SIZE);
cell.setFill(Color.WHEAT);
cell.setStroke(Color.GREY);
gridGroup.getChildren().add(cell);
})
);
// Add grid to board
Group board = new Group(gridGroup);
// add random tiles to board
IntStream.range(0,NUM_CELLS).boxed().forEach(i->
IntStream.range(0,NUM_CELLS).boxed().forEach(j->{
if(i==j || NUM_CELLS-i-1==j){
Label label = new Label();
label.setMinSize(TILE_SIZE, TILE_SIZE);
label.setPrefSize(TILE_SIZE, TILE_SIZE);
label.setMaxSize(TILE_SIZE, TILE_SIZE);
label.setStyle("-fx-background-color: red; -fx-background-radius: 50");
label.setLayoutX((i+0.5)*CELL_SIZE-TILE_SIZE/2);
label.setLayoutY((j+0.5)*CELL_SIZE-TILE_SIZE/2);
board.getChildren().add(label);
}
})
);
Bounds gameBounds = board.getLayoutBounds();
StackPane root = new StackPane(board);
// Listener to rescale and center the board
ChangeListener<Number> resize = (ov, v, v1) -> {
double scale = Math.min((root.getWidth() - MARGIN)/gameBounds.getWidth(),
(root.getHeight() - MARGIN)/gameBounds.getHeight());
board.setScaleX(scale);
board.setScaleY(scale);
board.setLayoutX((root.getWidth() - gameBounds.getWidth())/2d);
board.setLayoutY((root.getHeight() - gameBounds.getHeight())/2d);
};
root.widthProperty().addListener(resize);
root.heightProperty().addListener(resize);
Scene scene = new Scene(root);
// Maximum size of window
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
double factor = Math.min(visualBounds.getWidth()/(gameBounds.getWidth() + MARGIN),
visualBounds.getHeight()/(gameBounds.getHeight() + MARGIN));
primaryStage.setScene(scene);
primaryStage.setWidth((gameBounds.getWidth() + MARGIN) * factor);
primaryStage.setHeight((gameBounds.getHeight() + MARGIN) * factor);
primaryStage.show();
}
И это, как он будет выглядеть после некоторого изменения размеров окна:
Извините за поздний ответ и прием. Единственным недостатком является то, что это решение создает «Исключение в потоке» JavaFX Application Thread »java.lang.IllegalStateException: не для потока приложений FX; currentThread = JavaFX Application Thread', когда вы выполняете изменение размера и закрываете приложение. Это нормально, когда вы просто запускаете и закрываете его. – ChrLipp
Хм ... У меня нет такого исключения. Просто запустите мой код? Посмотрите на ссылку, опубликованную в моем ответе, вы найдете полностью работающее приложение. –
Происходит только при его максимизации и последующем закрытии (на macbook). – ChrLipp