java - 如何使用 javafx 在应用程序启动时运行多个不同阶段之一?

标签 java javafx javafx-2 javafx-8

我从 javafx 开始,但在理解如何正确建模以下情况时遇到了一些困难:

理想情况下,我希望有一个 main() 方法,它可以以某种方式允许我打开 LoginDialog 或者如果已经有可用的用户/密码组合disk,绕过登录并直接向用户显示 MainDialog

我的主要问题是,当我运行 Application.launch() 时,我需要提交一个 Application 实例,而在实现一个实例时,我没有对其 Stage 对象创建的任何控制,这为我创建了一个 catch-22。

我可以创建一个 LoginSceneMainScene 但随后我就无法控制 Stage 的标题等内容.

使用 javafx 解决此类问题的常用途径是什么?

谢谢

最佳答案

定义一个 Application 子类,并在 start() 方法中放置决定是否需要显示登录屏幕的逻辑(启动逻辑的正确位置是恰当命名的 start() 方法,而不是 main 方法):

public class MyApplication extends Application {

    private boolean loggedIn ;

    @Override
    public void start(Stage primaryStage) {

        loggedIn = checkLoginFromDisk();

        while (! loggedIn) {
            FXMLLoader loginLoader = new FXMLLoader(getClass().getResource("path/to/login.fxml"));
            Parent loginRoot = loginLoader.load();
            LoginController loginController = loginLoader.getController();
            Scene loginScene = new Scene(loginRoot);
            primaryStage.setScene(loginScene);
            primaryStage.setTitle("Login");
            primaryStage.showAndWait();
            // check login from controller and update loggedIn...
        }

        FXMLLoader mainLoader = new FXMLLoader(getClass().getResource("path/to/main.fxml"));
        Parent mainRoot = mainLoader.load();
        Scene mainScene = new Scene(mainRoot);
        primaryStage.setScene(mainScene);
        primaryStage.setTitle("My Application");
        primaryStage.sizeToScene();
        primaryStage.show();
    }

    private boolean checkLoginFromDisk() {
        // ... etc
    }

    // for environments not supporting direct launch of JavaFX:
    public static void main(String[] args) {
        launch(args);
    }
}

如果您不使用 FXML,则只需为“login”和“main”定义类而不是 FXML 文件 + Controller ,但结构保持不变:

public class LoginView {

    private final GridPane /* for example */ view ;

    public LoginView() {
        // setup UI, etc...
    }

    public Pane getView() {
        return view ;
    }

    public boolean checkLogin() {
        // etc...
    }
}

public class MainView {

    private BorderPane /* for example */ view ;

    public MainView() {
        // set up UI etc...
    }

    public Pane getView() {
        return view ;
    }
}

然后你的启动方法看起来像

@Override
public void start(Stage primaryStage) {

    loggedIn = checkLoginFromDisk();

    while (! loggedIn) {
        LoginView loginView = new LoginView();
        Scene loginScene = new Scene(loginView.getView());
        primaryStage.setScene(loginScene);
        primaryStage.setTitle("Login");
        primaryStage.showAndWait();
        loggedIn = loginView.checkLogin();
    }
    MainView mainView = new MainView();
    Scene mainScene = new Scene(mainView.getView());
    primaryStage.setScene(mainScene);
    primaryStage.setTitle("My Application");
    primaryStage.sizeToScene();
    primaryStage.show();
}

显然,您可以根据需要以多种不同的方式重构它(重用相同的登录类或 fxml 实例、为主视图使用不同的阶段等)。

请注意,不需要使用传递给 start() 方法的阶段。因此,如果您希望独立类封装包含登录场景和主场景的阶段,您可以添加以下类:

public class LoginStage extends Stage {

    private final LoginView loginView ;
    public LoginStage() {
        loginView = new LoginView();
        setScene(new Scene(loginView.getView());
        setTitle("Login");
    }

    public boolean checkLogin() {
        return loginView.checkLogin(); 
    }
}

并类似地创建一个 MainStage 类。 (在基于 FXML 的版本中,LoginStage 保存对 LoginController 的引用,并且仅在构造函数中加载 FXML,而不是实例化 LoginView类。)然后

public class MyApplication extends Application {

    private boolean loggedIn ;

    @Override
    public void start(Stage ignored) {
        loggedIn = checkLoginFromDisk();
        while (! loggedIn) {
            LoginStage login = new LoginStage();
            loginStage.showAndWait();
            loggedIn = loginStage.checkLogin();
        }
        new MainStage().show();
    }

    // ...
} 

关于java - 如何使用 javafx 在应用程序启动时运行多个不同阶段之一?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36632119/

相关文章:

java - 准备语句因 DB2 SQL 错误而失败

java - 如何在 Slick2D 中的随机位置接触后重生矩形?

java - 在 JavaFX 中使用 WebView 会破坏 Linux 上的 UI

java - SequentialTransition .stop() 不会等到过渡结束其循环

javafx 8 兼容性问题 - FXML 静态字段或方法

deployment - 如何使用 32 位和 64 位的 jnlp 正确部署桌面 JavaFx 2.0 应用程序?

java - 如何停止我的 JTextPane 吞下键盘快捷键(加速器)?

Java boolean 递归方法用于字符串计数

image - 使用 FileChooser 保存可写图像图像

java - 如何判断 Mediaplayer 何时完成播放音频