Я хочу создать служебный инструмент, который изменяет размер по вертикали, когда дети добавляются/удаляются из VBox. Дети изменяются посредством пользовательского ввода. Размер окна приложения не может быть изменен пользователем.
Я создал следующий файл FXML:
<AnchorPane fx:id = "rootPane"
maxHeight = "-Infinity" maxWidth = "-Infinity"
minHeight = "-Infinity" minWidth = "-Infinity"
prefHeight = "400.0" prefWidth = "600.0"
xmlns = "http://javafx.com/javafx/17.0.2-ea"
xmlns:fx = "http://javafx.com/fxml/1"
fx:controller = "myProject.controller.DynamicResizeController">
<children>
<VBox fx:id = "vBox"
layoutX = "148.0" layoutY = "144.0"
prefHeight = "200.0" prefWidth = "200.0">
<children>
<Label text = "This is a label" />
<Button fx:id = "addButton"
onAction = "#handleAddButtonClick" text = "Add Element" />
<Button fx:id = "removeButton"
text = "Remove Element" />
</children>
</VBox>
</children>
</AnchorPane>
и класс контроллера:
public class DynamicResizeController {
@FXML
private VBox vBox;
@FXML
private AnchorPane rootPane;
public void handleAddButtonClick(ActionEvent event) {
Label label = new Label("New Element added!");
vBox.getChildren().add(label);
calculateAndResize();
}
private void calculateAndResize() {
double totalHeight = 0;
for (Node child : vBox.getChildren()) {
totalHeight += child.prefHeight(-1) + child.getLayoutY();
}
resizeStage(totalHeight);
}
private void resizeStage(double height) {
// set height of stage to height
}
}
Основной класс довольно простой:
public class DynamicResizeApplication extends Application {
@Override
public void start(Stage stage) throws Exception {
FXMLLoader fxmlLoader = new FXMLLoader(DynamicResizeApplication.class.getResource("view/dynamic-resize-view.fxml"));
Scene scene = new Scene(fxmlLoader.load());
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Как мне установить высоту сцены? Я не нашел способа получить к нему доступ в классе контроллера.
Я не пробовал, но вам не нужно рассчитывать новую высоту сцены. Просто добавьте элементы в узел сцены и вызовите stage.sizeToScene(). Как только панель из вашего FXML добавлена в окно, вы можете найти ее на этапе (Stage) mynode.getScene().getWindow(), где mynode — это некоторый @FXML аннотированный узел в контроллере.
Посмотрите, может ли это помочь.




+1 за то, что предложил @jewelsea. Действительно, вам нужно использовать метод sizeToScene(), чтобы вычисления выполнялись автоматически и изменяли размер окна.
Однако вызов sizeToScene() не всегда сделает ваше окно компактным по ширине его содержимого. Вам необходимо учитывать некоторые другие факторы, касающиеся того, как работает sizeToScene().
В первую очередь любые настройки prefWidth/prefHeight будут влиять на вычисления sizeToScene(). И наряду с этим играют роль настройки мин/макс.
Итак, мое предложение:
Итак, что касается вашего вопроса: я не уверен, почему вы рассмотрели AnchorPane, но все настройки pref/min/max не требуются. По этой причине, даже если вы используете sizeToScene(), размер вашего окна не изменится.
Ниже приведена демонстрация и код fxml после удаления всех настроек размера и последующего вызова sizeToScene():
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<AnchorPane fx:id = "rootPane" xmlns = "http://javafx.com/javafx/17.0.2-ea" xmlns:fx = "http://javafx.com/fxml/1" fx:controller = "myProject.controller.DynamicResizeController">
<children>
<VBox fx:id = "vBox" layoutX = "148.0" layoutY = "144.0" >
<children>
<Label text = "This is a label" />
<Button fx:id = "addButton" onAction = "#handleAddButtonClick" text = "Add Element" />
<Button fx:id = "removeButton" text = "Remove Element" />
</children>
</VBox>
</children>
</AnchorPane>
И код вашего контроллера:
public void handleAddButtonClick(ActionEvent event) {
Label label = new Label("New Element added!");
vBox.getChildren().add(label);
vBox.getScene().getWindow().sizeToScene();
}
Я не уверен, почему у вас есть панель привязки для корня и как вы собираетесь поступать с макетом, если добавляете больше дочерних элементов, чем может быть отображено на сцене. Возможно, вам следует использовать ListView или хотя бы добавить ScrollPane.