【问题标题】:JavaFX: Dynamically added VBox does not show upJavaFX:动态添加的 VBox 不显示
【发布时间】:2016-11-08 19:12:24
【问题描述】:

我正在开发一个需要 VBox 的“表格”表示的项目。我的应用程序分层布局是 GridPane -> VBox(在其中一个单元格中)-> VBoxes(在彼此之上显示不同的数据集)-> Data。我有两个场景。

数据显示在场景 1。用户可以通过表单和单击场景 2 上的按钮添加数据。然后,添加的数据应显示在现有数据的下方,作为场景 1 的父 VBox 内的 VBox再次。

下面是清晰的代码:

我的场景 1 .fxml 文件如下所示(简化):

<GridPane fx:id="grid" fx:controller="application.Controller">
  [here: ColumnConstraints]
  <children>
    <VBox fx:id="parentBox" GridPane.columnIndex="0" GridPane.rowIndex="1"/>
    <Button fx:id="goToScene2" text="+" onAction="#goToScene2"/> 
  </children>  
</GridPane>

场景 2 只有一个按钮和一个 TextField:

<GridPane fx:id="grid" fx:controller="application.AddDataController">
  [here: ColumnConstraints]
  <children>
    <Button fx:id="addData" text="add" onAction="#bAddData"/> 
    <TextField fx:id="data"/>
  </children>  
</GridPane>

我的 Scene 1 控制器(控制器)如下所示:

public class Controller implements Initializable  {
  @FXML Button goToScene2;
  @FXML VBox parentBox;

  @Override
  public void initialize(URL location, ResourceBundle resources) {
  }

  public void addData(String s) {
    Label lbl = new Label(s);
    VBox dataBox = new VBox();
    dataBox.setPadding(new Insets(15, 5, 15, 5));
    dataBox.setSpacing(5);
    dataBox.setMaxHeight(80);
    dataBox.getChildren().add(lbl);
    parentBox.getChildren().add(dataBox);
  }
}

之所以这样设计,是因为 dataBox 包含的元素比标签多,但在这种情况下,这似乎与我无关。

我的场景 2 控制器 (addDataController) 如下所示:

@FXML Button addData;
@FXML TextField data;

@FXML protected void bAddData(){
  String content = data.getText();    
  FXMLLoader fxmlLoader = new FXMLLoader();
  Pane p = fxmlLoader.load(getClass().getResource("scn1.fxml").openStream());
  Controller cont = (Controller) fxmlLoader.getController();

  cont.addData(content);
}

所以,当在场景 2 中点击 Add-Data-Button 时,触发的方法会将输入的数据传递给场景 1 的控制器。这是因为新数据现在应该显示在场景 1 中。

我觉得逻辑不起作用(在此处编辑),因为当我要求时

System.out.println(parentBox.getChildren().size();

在添加数据之前和之后,它始终只有一个 Child,即使它应该还有一个...

如果我人为地填充一个字符串数组并将所有内容从 addData 移动到(String s) 到 Initialize(...),它确实可以工作并且数据在父 VBox 中显示为 VBox。

我没有发布主类,因为加载控制器和场景更改不是问题。

非常感谢大家的帮助! :)

【问题讨论】:

  • 我不相信您用来调用AddData(content)Controller const 实例与您的主要Scene 正在使用的Controller 实例相同。 FXMLLoader 正在创建一个不在场景图中的新实例。一个简单的解决方法可能是将主场景控制器传递给第二个场景。你的goToScene 方法是什么样的?
  • 这实际上是我从未见过的。但是,使用的控制器是在 .fxml 文件中定义的,因此我无法从任何其他类访问它。它从未在 JavaFX 代码中加载。将 Controller 类设为静态也没有用。
  • 对不起。 goToScene 方法调用主程序类中的一个方法,并传递一个String。此字符串在 switch-case 语句中处理并触发 currentStage.setScene(newScene)
  • @OttPrime 是正确的。每次您在FXMLLoader 上调用load 时,它都会创建一个新的控制器实例。由于您从不显示 p,因此您正在更改其数据的控制器连接到一个从不显示的 UI 元素。加载时需要从FXMLLoader 获取控制器并显示
  • 是的,这听起来很合理。但这不是追自己的尾巴吗…….fxml 文件包含有关显示数据的所有信息。我只想将一个子节点附加到其中的一个节点,我需要 ControllerController 类在.fxml 中定义时如何实例化?我可以访问同一个实例(而不总是创建一个新实例)吗?

标签: javafx javafx-8 vbox efxclipse


【解决方案1】:

只是为了提供更详细的信息,以及一个我不知道如何实现的想法。

这是我的主要课程:

@Override
public void start(Stage primaryStage) {
  currentStage = primaryStage;
  Parent root = FXMLLoader.load(getClass().getResource("Scene1.fxml"));
  scene1 = new Scene(root);
}

此时我可以加载控制器并制作一个通过控制器的吸气剂吗?所以我在整个程序中只有一个实例。

我尝试插入:

FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.load(getClass().getResource("Scene1.fxml").openStream());
Controller controller = (Controller) fxmlLoader.getController();

之后

Parent root ...

线。但这是加载 .xml 文件两次。我怎样才能很好地连接这两个部分?

非常感谢您的耐心等待!

编辑:::::::::: 以下代码对我有用:

@Override
public void start(Stage primaryStage) {
  currentStage = primaryStage;
  FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Scene1.fxml"));
  Parent root =(Parent) fxmlLoader.load();
  controller = (Controller) fxmlLoader.getController();
}

现在,我可以向主类询问controller,它总是通过那个单一实例。

感谢您为我指明了正确的方向! :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多