Должно ли указание CSS-границ JavaFX для содержимого GridPane сворачивать размер?
Я пытался расположить сцену JavaFX, используя GridPane
когда я столкнулся со следующей проблемой. Если я настрою сетку с соответствующими ограничениями и добавлю новые экземпляры StackPane
Кроме того, размер сцены, сцены и ее содержимого по умолчанию обеспечивает видимость содержимого:
Тем не менее, если я добавлю стиль JavaFX CSS, указав границу для нового экземпляра StackPane
прежде чем добавить его в GridPane
тогда размер по умолчанию для вещей, кажется, завершается:
Мой код выглядит следующим образом:
public static void main(final String[] args) {
Platform.startup(() -> {});
Platform.runLater(() -> {
final GridPane gridPane = new GridPane();
final Scene scene = new Scene(gridPane);
final Stage stage = new Stage();
stage.setScene(scene);
final List<StackPane> panes = new ArrayList<>();
for (int i = 0; i < 4; i++) {
// Create a new pane with a random background color for
// illustration
final StackPane p = createNewPane();
panes.add(p);
// The addition / removal of the following line affects the
// layout.
p.setStyle("-fx-border-width:2px;-fx-border-color:red");
}
for (int r = 0; r < 2; r++) {
final RowConstraints rc = new RowConstraints();
rc.setPercentHeight(50);
gridPane.getRowConstraints().add(rc);
}
for (int c = 0; c < 2; c++) {
final ColumnConstraints cc = new ColumnConstraints();
cc.setPercentWidth(50);
gridPane.getColumnConstraints().add(cc);
}
for (int r = 0, i = 0; r < 2; r++) {
for (int c = 0; c < 2; c++) {
gridPane.add(panes.get(i++), c, r);
}
}
stage.show();
});
}
Любопытно, если я перееду stage.show()
сразу после того, как я установил сцену, то все отлично работает даже с CSS.
Может ли кто-нибудь помочь мне понять, один, это ожидаемое поведение, и два, почему порядок выполнения stage.show()
имеет значение?
Спасибо!
1 ответ
В чем проблема
Ваш пример немного неоднозначен. Вы не устанавливаете предпочтительный размер чего-либо, добавленного в Сцену, в любое время. Таким образом, платформа JavaFX действительно может делать все, что угодно, с точки зрения определения размеров. Установка предпочтительного размера в процентах отличается от установки предпочтительного абсолютного размера. Размер в процентах является относительным, поэтому возникает вопрос, относительно чего? и ответ на этот вопрос неясен.
Что касается того, почему это происходит:
// The addition / removal of the following line affects the
// layout.
p.setStyle("-fx-border-width:2px;-fx-border-color:red");
Я не мог сказать. Я предполагаю, что использование CSS вызывает некоторую дополнительную логику компоновки, которая влияет на изменение размера при отсутствии каких-либо подсказок по размеру.
Как это исправить
В любом случае, решение состоит в том, чтобы просто сделать вещи более понятными и указать предпочтительный размер, по крайней мере, для чего-то в приложении, тогда приложение будет первоначально измерено до этого предпочтительного размера.
Вот пример:
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Starter {
public static void main(String[] args) {
Platform.startup(() -> {});
Platform.runLater(() -> {
final GridPane gridPane = new GridPane();
final Scene scene = new Scene(gridPane);
final Stage stage = new Stage();
stage.setScene(scene);
final List<StackPane> panes = new ArrayList<>();
for (int i = 0; i < 4; i++) {
// Create a new pane with a random background color for
// illustration
final StackPane p = createNewPane();
panes.add(p);
// The addition / removal of the following line affects the
// layout.
p.setStyle("-fx-border-width:2px;-fx-border-color:red");
}
for (int r = 0; r < 2; r++) {
final RowConstraints rc = new RowConstraints();
rc.setPercentHeight(50);
gridPane.getRowConstraints().add(rc);
}
for (int c = 0; c < 2; c++) {
final ColumnConstraints cc = new ColumnConstraints();
cc.setPercentWidth(50);
gridPane.getColumnConstraints().add(cc);
}
for (int r = 0, i = 0; r < 2; r++) {
for (int c = 0; c < 2; c++) {
gridPane.add(panes.get(i++), c, r);
}
}
stage.show();
});
}
private static final Random random = new Random(42);
private static StackPane createNewPane() {
StackPane pane = new StackPane();
pane.setBackground(
new Background(
new BackgroundFill(
randomColor(), null, null
)
)
);
pane.setPrefSize(150, 100);
return pane;
}
private static Color randomColor() {
return Color.rgb(
random.nextInt(256),
random.nextInt(256),
random.nextInt(256)
);
}
}
Ключевой частью решения является вызов:
pane.setPrefSize(150, 100);
который устанавливает предпочтительный размер для стековых панелей, которые были размещены в вашем макете.
В качестве альтернативы, вместо выполнения предпочтительного размера снизу вверх путем установки предпочтительного размера для каждой из стековых панелей, вы также можете выполнить аналогичную задачу с точки зрения сверху вниз, установив вместо этого соответствующие ограничения на GridPane, например:
gridPane.setPrefSize(300, 200);
Заметка
Я бы посоветовал использовать класс приложения JavaFX вместо вызова Platform.startup(), если только нет веской причины использовать последний (что в данном случае есть - взаимодействие с Swing, как вы отметили в своем комментарии).