JavaFX - FileChooser window 正在打开,但默认的 initialModality 不工作

JavaFX - The FileChooser window is opening but the default initialModality isn't working

我创建了一个应用程序,我必须在其中单击 MenuItem "Open..." 才能打开 FileChooser。 FileChooser 确实打开了,但问题是我可以单击或关闭第一个 window,而此 FileChooser 仍处于打开状态。

我的代码有问题吗?将 primaryStage 作为 fileChooser.showOpenDialog(primaryStage); 的参数是错误的吗?

这些是我的声明

private Stage primaryStage;

这是我的启动方法。

@Override
public void start(Stage primaryStage) {
    this.primaryStage = primaryStage;
    primaryStage.setTitle("Ontology - Language Disorders");
    primaryStage.centerOnScreen();
    initRootLayout();
    showOntologyOverview();
    primaryStage.show();
}

这是我的 OpenDialog

@FXML
private void handleOpenMenuItem(ActionEvent event){
    FileChooser fileChooser = new FileChooser();
    fileChooser.setTitle("Open Resource File");
    fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("OWL (*.owl)", "*.owl"));
    fileChooser.showOpenDialog(primaryStage);
}

我的初始化根布局:

public void initRootLayout() {
    try {
        // Load root layout from fxml file.
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(MainApp.class.getResource("RootLayout.fxml"));
        rootLayout = (BorderPane) loader.load();
        // Show the scene containing the root layout.
        Scene scene = new Scene(rootLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

您正在使用 Application class 作为 FXML 的控制器 class。这是非常混乱的,你应该避免它。

事情是这样的:

  1. 您启动应用程序。这会导致 FX 工具包被初始化,FX 应用程序线程启动,您的 Application subclass 实例被创建,Stage 被创建并且 start(...)在该实例上调用,在 FX 应用程序线程上。
  2. 您的start方法设置了启动序列
  3. 创建的实例的primaryStage字段
  4. 您创建一个 FXMLLoader 并加载 FXML 文件。
  5. FXMLLoader 创建了控制器 class 的一个实例(恰好是 Application subclass)。然后它初始化该实例上所有 @FXML 注释的字段,并注册处理程序方法。请注意,primaryStage 字段从未在此实例上初始化。

当用户按下"Open"MenuItem时,handleOpenMenuItem()方法在第4步创建的实例(不是第1步创建的实例)上被调用。您创建 FileChooser,并调用 showOpenDialog(...) 并传入 primaryStage 的值。由于 primaryStage 在这种情况下是 null,文件选择器没有所有者 window,因此无法实现任何有意义的模态。

要解决此问题,请为您的控制器创建一个单独的 class。您可以通过在场景中的任何节点上调用 getScene().getWindow() 来获取 window。