如何在 JavaFX 独立应用程序中创建启动画面作为预加载器?

How to create splash screen as a Preloader in JavaFX standalone application?

我创建了一个预加载器(基于以下教程),它应该显示主应用程序的启动画面。

9.3.4 使用预加载器显示应用程序初始化进度 http://docs.oracle.com/javafx/2/deployment/preloaders.htm

public class SplashScreenLoader extends Preloader {

    private Stage splashScreen;

    @Override
    public void start(Stage stage) throws Exception {
        splashScreen = stage;
        splashScreen.setScene(createScene());
        splashScreen.show();
    }

    public Scene createScene() {
        StackPane root = new StackPane();
        Scene scene = new Scene(root, 300, 200);
        return scene;
    }

    @Override
    public void handleApplicationNotification(PreloaderNotification notification) {
        if (notification instanceof StateChangeNotification) {
            splashScreen.hide();
        }
    }

}

每次 运行 我 IDE (IntelliJ IDEA) 中的主应用程序时,我都想 运行 预加载器。

我也遵循了 IntelliJ 中预加载器的打包规则: https://www.jetbrains.com/idea/help/applications-with-a-preloader-project-organization-and-packaging.html

当我 运行 主应用程序时,预加载器没有启动,所以我想我遗漏了什么。我是预加载器的新手,我不明白在独立应用程序中将主应用程序与预加载器连接的机制是什么。

IDE 还不擅长添加预加载器。查看程序 jar 文件中的清单并确保存在以下行:

JavaFX-Preloader-Class: SplashScreenLoader

您可以 运行 使用 LauncherImpl 像这样。 . .

public class Main {
   public static void main(String[] args) {
      LauncherImpl.launchApplication(MyApplication.class, SplashScreenLoader.class, args);
   }
}

而 class MyApplication 会像这样。 . .

public class MyApplication extends Application {

    @Override
    public void start(Stage primaryStage) {
        ....
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}

可能来不及了,这也可以帮助别人。 对我来说,我使用 JavaFX 服务和任务在 JavaFX 独立应用程序中创建启动画面作为预加载器。这是因为我项目的背景。

创建 AnchorPane 和进度窗格

@FXML
private AnchorPane anchorPane;
private MaskerPane progressPane;


public static void main(String[] args) {
    launch(args);
}

    @Override
public void init() throws Exception {
    progressPane = new MaskerPane();
    progressPane.setText(bundle.getString("root.pleaseWait"));
    progressPane.setVisible(false);
    AnchorPane.setLeftAnchor(progressPane, 0.0);
    AnchorPane.setTopAnchor(progressPane, 0.0);
    AnchorPane.setRightAnchor(progressPane, 0.0);
    AnchorPane.setBottomAnchor(progressPane, 0.0);
    anchorPane.getChildren().add(progressPane);
}

@Override
public void start(Stage initStage) {
  //.....
    initRoot();
 //.....

}

按如下方式创建启动画面服务:

private final Service<Void> splashService = new Service<Void>() {
    @Override
    protected Task<Void> createTask() {
        return new Task<Void>() {
            @Override
            public Void call() throws Exception {
                //main code, the code who take time
                //or
                //Thread.sleep(10000);
                return null;
            }
        };
    }
};

加载主屏幕时启动服务和show/hide initRoot 上的progressPane:

   public void initRoot() {
    try {
        //....

        splashService.restart();
        //On succeeded, do this
        splashService.setOnRunning(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent event) {
                //Show mask on succeed
                showMask(Boolean.TRUE);
            }
        });
        splashService.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent event) {
                splashService.cancel();
                 //Hide mask on succeed
                showMask(Boolean.FALSE);
            }
            });    
            //.....
            primaryStage.show();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

要show/hide进度...

showMask(boolean value){
        progressPane.setVisible(value);
};