JavaFX 根据 VBox 元素的数量动态调整窗口大小

问题描述 投票:0回答:1

我想构建一个实用工具,当从 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);
  }
}

如何设置舞台高度?我没有找到访问控制器类中我的舞台的方法。

java javafx
1个回答
0
投票

+1 对于@jewelsea 的建议。事实上你需要使用

sizeToScene()
方法让计算自动完成并调整窗口大小。

话虽如此,调用

sizeToScene()
并不总是能让你的窗口压缩到其内容宽度。您需要考虑有关
sizeToScene()
工作原理的一些其他因素。

主要是任何 prefWidth/prefHeight 设置都会影响 sizeToScene() 计算。除此之外,最小/最大设置也发挥了作用。

所以我的建议是:

  • 您需要遍历场景中的所有节点,以查看您需要的首选项/最小/最大设置。如果不需要,请删除任何 min/max/pref 声明。
  • 我知道,如果您从 SceneBuilder 生成 fxml,您将获得为您生成的所有属性。 不要爱上他们!。检查 FXML 中的每个属性,如果您确实不需要它(或不知道它),请将其删除。如果它没有按预期工作,那么您就会知道要考虑哪些属性。 (这就是你将学习的方式)

所以回到你的问题:我不确定你为什么考虑 AnchorPane,但 pref/min/max 的所有设置都不是必需的。因此,即使您使用

sizeToScene()
,您的窗口也不会调整大小。

下面是删除所有尺寸设置然后调用 sizeToScene() 后的 fxml 的演示和代码:

<?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();
}
© www.soinside.com 2019 - 2024. All rights reserved.