提问者:小点点

JavaFX 第二次启动模式对话框时出现“已设置为另一个场景的根”异常


我正在构建一个简单的JavaFX应用程序,它要求我在主应用程序窗口前面启动一个模式窗口。使用下面的代码,我可以启动模态窗口1次并关闭它。如果我再次尝试启动它,我会收到:

 java.lang.IllegalArgumentException: BorderPane[id=root, styleClass=root]is already set as root of another scene

我正在使用此处描述的Spring Controller/FXML视图依赖注入方法:http://www.zenjava.com/2012/02/20/porting-first-contact-to-spring/

我能够用程序创建一个场景并隐藏/显示一个简单的对话框,而无需使用FXML/Spring Controller注入。这很好用。

我无法解释“已经设置为root”异常,因为每次单击“开始”按钮时,我都会创建一个新场景()。当模式窗口第一次关闭时,第一个场景应该已经被破坏了。

相关文件如下。

MainTabPanel.java-我的应用程序的主视图。这包含单击以启动模式窗口的“start Button”。

ActivePresentation控制器/视图被注入为:<code>@Inject private ActivePresentation ActivePresentation

下面是initialize()方法,它试图在单击startButton时启动模式。

@FXML
 public void initialize()
 {
      availableReceiversIdColumn.setCellValueFactory(new PropertyValueFactory("id"));
      availableReceiversFirmwareVersionColumn.setCellValueFactory(new PropertyValueFactory("firmwareVersion"));
      availableReceiversModelColumn.setCellValueFactory(new PropertyValueFactory("model"));
      availableReceiversChannelColumn.setCellValueFactory(new PropertyValueFactory("channel"));
      ObservableList<String> responseTypes = FXCollections.observableArrayList();
      responseTypes.add("Single Response Alpha");
      responseTypes.add("Single Response Numeric");
      responseTypeChoiceBox.setItems(responseTypes);

      startButton.setOnAction(new EventHandler<ActionEvent>()
      {
           @Override
           public void handle(ActionEvent e)
           {
                Stage stage = new Stage();
                stage.initModality(Modality.APPLICATION_MODAL);

                presentationResponseService.startPresentation();
                activePresentation.populateResponses(null);
                activePresentation.populateResults(null);

                Scene activePresentationScene = new Scene(activePresentation.getView());
                activePresentationScene.getStylesheets().add("styles.css");

                stage.setScene(activePresentationScene);
                stage.setTitle("Active Presentation");
                stage.showAndWait();
           }
      });
 }

关闭按钮在模式对话框中定义如下。

closeButton.setOnAction(new EventHandler<ActionEvent>()
      {
           @Override
           public void handle(ActionEvent e)
           {
                presentationResponseService.closePresentation();
                Stage stage = (Stage) root.getScene().getWindow();
                stage.close();
           }
      });

ActivePresentingbean和FXML加载程序的基于Java的Spring配置如下。

@Bean
 public ActivePresentation activePresentation()
 {
      return loadPresenter("/fxml/ActivePresentation.fxml");
 }

FXML加载程序

private <T> T loadPresenter(String fxmlFile)
 {
      try
      {
           FXMLLoader loader = new FXMLLoader();
           loader.load(getClass().getResourceAsStream(fxmlFile));
           return (T) loader.getController();
      } catch (IOException e)
      {
           throw new RuntimeException(String.format("Unable to load FXML file '%s'", fxmlFile), e);
      }
 }

共2个答案

匿名用户

当我自动安装弹出窗口时,我遇到了这个问题。它第一次工作,但当我第二次关闭弹出窗口时,我收到了这个错误。
我通过检查弹出窗口是否已经有一个场景来管理,请参阅下面的代码:

if (window.getScene() == null) {
    Scene scene = new Scene(window);
    stage.setScene(scene);
} else {
    stage.setScene(window.getScene());
}

匿名用户

似乎,舞台仍然在JFX的控制之下(逻辑:您可以尝试再次打开它)。

每次都创建一个阶段,而前一个阶段还活着,所以,你能尝试在阶段.关闭()附近添加阶段. setScene(null)吗?

还是每次都使用相同的场景或相同的舞台?

我在 JFX 的这一部分没有看到任何错误:节点是相同的,阶段(和其中的场景)是不同的。所以有两种方法:只使用 1 个舞台场景,或者每次创建不同的边框窗格实例。