我从 javafx 开始,但在理解如何正确建模以下情况时遇到了一些困难:
理想情况下,我希望有一个 main()
方法,它可以以某种方式允许我打开 LoginDialog
或者如果已经有可用的用户/密码组合disk,绕过登录并直接向用户显示 MainDialog
。
我的主要问题是,当我运行 Application.launch()
时,我需要提交一个 Application
实例,而在实现一个实例时,我没有对其 Stage
对象创建的任何控制,这为我创建了一个 catch-22。
我可以创建一个 LoginScene
和 MainScene
但随后我就无法控制 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/