我正在构建一个简单的 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);
}
}