How to create splash screen as a Preloader in Java

2019-06-16 20:48发布

I created a Preloader (based on the following tutorial) that should display a splash screen for the main application.

9.3.4 Using a Preloader to Display the Application Initialization Progress 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();
        }
    }

}

I'd like to run preloader each time I run the main application in my IDE (IntelliJ IDEA).

I also followed the packaging rules for preloaders in IntelliJ: https://www.jetbrains.com/idea/help/applications-with-a-preloader-project-organization-and-packaging.html

When I run the main application the preloader doesn't start, so I suppose I'm missing something. I'm new to Preloaders and I don't understand what is the mechanism to connect the main app with the preloader in standalone application.

3条回答
手持菜刀,她持情操
2楼-- · 2019-06-16 21:13

You can run using LauncherImpl like this . . .

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

And the class MyApplication would be like this . . .

public class MyApplication extends Application {

    @Override
    public void start(Stage primaryStage) {
        ....
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}
查看更多
Root(大扎)
3楼-- · 2019-06-16 21:21

The IDEs aren't great at adding preloaders yet. Take a look at the Manifest in your program's jar file and make sure this line is present:

JavaFX-Preloader-Class: SplashScreenLoader
查看更多
Luminary・发光体
4楼-- · 2019-06-16 21:33

May be too late, this can also help somebody. For me, i used JavaFX service and task to create splash screen as a Preloader in JavaFX standalone application. This, because the contexte of my project.

Create the AnchorPane and the progress Pane

@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();
 //.....

}

Create the splash screen service as this:

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;
            }
        };
    }
};

Start service and show/hide the progressPane on initRoot when loading the main screen:

   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();
        }
    }

To show/hide the progress...

showMask(boolean value){
        progressPane.setVisible(value);
};
查看更多
登录 后发表回答