如何从控制器访问 JavaFx Stage?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33932309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:09:24  来源:igfitidea点击:

How to access a JavaFx Stage from a Controller?

javajavafxcontrollerfxml

提问by Sargon1

I'm converting a pure JavaFx app, in which the code below worked fine when put all in one class, to a FXML one, where the Stage declaration and the button handler are in separate classes. In the a Controller, I'm trying to implement a method that will allow the user to choose a directory and store it in a variable for later use:

我正在将一个纯 JavaFx 应用程序(其中下面的代码在将所有内容放在一个类中时运行良好)转换为 FXML 应用程序,其中 Stage 声明和按钮处理程序位于不同的类中。在控制器中,我试图实现一种方法,该方法将允许用户选择一个目录并将其存储在变量中以供以后使用:

private File sourceFile;
DirectoryChooser sourceDirectoryChooser;

@FXML
private void handleSourceBrowse() {
        sourceDirectoryChooser.setTitle("Choose the source folder");
        sourceFile = sourceDirectoryChooser.showDialog(theStage);
}

However, "theStage", a Stage which the method requires, only exists(if that's the right terminology) in FolderSyncer4.java:

但是,该方法需要的舞台“theStage”仅存在于 FolderSyncer4.java 中(如果这是正确的术语):

public class FolderSyncer4 extends Application {

    final String FOLDER_SYNCER = "FolderSyncer";

    Stage theStage;

    @Override
    public void start(Stage primaryStage) throws Exception {
        theStage = primaryStage;

        //TODO do the FXML stuff, hope this works
        Parent root = FXMLLoader.load(getClass().getResource("FolderSyncerMainWindow.fxml"));
        theStage.setScene(new Scene(root, 685, 550));
        theStage.setTitle(FOLDER_SYNCER);
        theStage.show();
    }
}

How to I get around this? I need to have that method implemented again somehow, but suddenly I can't pass the stage as an argument.

我该如何解决这个问题?我需要以某种方式再次实现该方法,但突然间我无法将阶段作为参数传递。

采纳答案by Andreas Fester

In your situation, it is probably easiest to get the scene from the ActionEventparameter of your handler:

在您的情况下,从ActionEvent处理程序的参数中获取场景可能是最简单的:

@FXML
private void handleSourceBrowse(ActionEvent ae) {
    Node source = (Node) ae.getSource();
    Window theStage = source.getScene().getWindow();

    sourceDirectoryChooser.showDialog(theStage);
}

See JavaFX: How to get stage from controller during initialization?for some more information. I am not in favor of the highest rated answer though, since it adds a compile time dependency to the controller after the .fxmlfile has been loaded (after all that question was tagged with javafx-2, so not sure if the above approach already worked there, and also the context of the question looks a bit different).

请参阅JavaFX:如何在初始化期间从控制器获取舞台?了解更多信息。不过,我不赞成评分最高的答案,因为它.fxml在加载文件后向控制器添加了编译时依赖性(毕竟该问题被标记为javafx-2,所以不确定上述方法是否已经在那里工作,并且问题的上下文看起来有点不同)。

See also How do I open the JavaFX FileChooser from a controller class?

另请参阅如何从控制器类打开 JavaFX FileChooser?

回答by Jinu P C

Another way is define a static getter for the Stage and Access it

另一种方法是为舞台定义一个静态 getter 并访问它

Main Class

主类

public class Main extends Application {
    private static Stage primaryStage; // **Declare static Stage**

    private void setPrimaryStage(Stage stage) {
        Main.primaryStage = stage;
    }

    static public Stage getPrimaryStage() {
        return Main.primaryStage;
    }

    @Override
    public void start(Stage primaryStage) throws Exception{
        setPrimaryStage(primaryStage); // **Set the Stage**
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }
}

Now you Can access this stage by calling

现在您可以通过调用访问此阶段

Main.getPrimaryStage()

Main.getPrimaryStage()

In Controller Class

在控制器类中

public class Controller {
public void onMouseClickAction(ActionEvent e) {
    Stage s = Main.getPrimaryStage();
    s.close();
}
}