0

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

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

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

我能够以编程方式创建一个场景并隐藏/显示一个简单的对话框,而无需使用 FXML / Spring Controller 注入。这工作正常。

我无法解释“已设置为 root”异常,因为每次单击 startButton 时我都会创建一个新的 Scene()。每当模态窗口第一次关闭时,第一个场景就应该被销毁。

相关文件如下。

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

ActivePresentation 控制器/视图被注入为: @Inject private ActivePresentation activePresentation;

下面是单击 startButton 时尝试启动模式的 initialize() 方法。

@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 在模态对话框中定义如下。

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

ActivePresentation bean 和 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);
      }
 }
4

2 回答 2

1

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

if (window.getScene() == null) {
    Scene scene = new Scene(window);
    stage.setScene(scene);
} else {
    stage.setScene(window.getScene());
}
于 2015-04-02T11:38:26.647 回答
0

Seems, the stage is still under control of JFX (logic : you can try yo open it again).

And you create a stage each time while previous is still alive, so, could you try to add stage.setScene(null) near stage.close().

Or use the same scene or the same stage each time?

I don't see any bug in this part of JFX : node is the same, stages (and scenes in it) are different. So there are 2 ways : use only 1 stage+scene, or create different border pane instances each time.

于 2013-05-02T16:57:52.440 回答