如何在嵌套控制器中初始化对话框 window

How to initialize dialog window in nested controller

我正在使用 Java8 和 JavaFX 开发 GUI 应用程序。主 window 有一个按钮,应该打开新的 window(带有它自己的 fxml)。到目前为止,每次按下按钮时我都会加载 fxml,但由于新的 window 有大量控件,它(令人惊讶地)需要一些时间(大约 0.5-1 秒)才能打开弹出窗口,因此我'我们更改了代码,以便主控制器在其初始化方法中加载弹出式 fxml,并且只要单击按钮,就会显示预加载的 window。 一切正常,但现在我无法在新 window 上设置 initOwner(...),因为我无权访问 initilize 方法中的 window 对象。我知道我不必设置 initOwner,但是我在开始菜单上有两个应用程序 windows(我想避免)。任何想法如何解决这个问题? 另外,在 JavaFX 中显示新 windows/dialogs 的标准方式是什么,我应该在每次事件发生时加载一个 fxml 还是只加载 show/hide 预加载的?

您可以延迟加载 fxml。即不是在应用程序启动时或不是在每次单击按钮时,而是在请求时:

private Parent popupPane;
private PopupPaneController popupPaneController;

private void openPopup( ActionEvent event ) {
    if (popupPane == null) {
        popupPane = FXMLLoader.load(...);
        popupPaneController = // get it from FXMLLoader. Search this site for how
    }
    popupPaneController.updatePopupContent(newVals);
    Stage popup = new Stage();
    popup.initOwner(primaryStage);
    stage.setScene(new ScrollPane(popupPane));
    stage.show();
}

注意,如果缓存了popup的内容window,以后可以设置initOwner()。还要检查 Alert class as an alternative for popup. See examples of it.

在显示预加载的 scene/window 时,您可能需要更新弹出窗口中显示的数据。为此,在弹出控制器的 class 中实现一个 updatePopupContent(newVals) 方法,并像上面的代码一样在每次单击按钮时调用它。

您可以在 initialize() 方法中加载一次 FXML,然后在需要时延迟初始化对话框 window。即

public class Controller {

    private Parent dialogPane ;
    private Stage dialog ;

    @FXML
    private Button button ;

    public void initialize() throws IOException {
        dialogPane = FXMLLoader.load(getClass().getResource("dialog.fxml"));
    }

    @FXML
    private void handleButtonPress() {
        getDialog().show();
    }

    private Stage getDialog() {
        if (dialog == null) {
            Scene scene = new Scene(dialogPane);
            dialog = new Stage();
            dialog.setScene(scene);
            dialog.initOwner(button.getScene().getWindow());
        }
        return dialog ;
    }
}