显示的预加载器和阶段之间的延迟

Delay between Preloader and Stage shown

我有一个程序使用简单的预加载器,而 init() 方法创建主图形用户界面。一切正常,但在 init() 方法完成并且预加载器消失后,在主舞台出现之前会有明显的延迟。我说明显是因为它可能长达 7 秒,足以让用户感到困惑。

我试图在start()方法中尽可能少地放置:

public void start(Stage stage) {
    /*Scene*/
    scene = new Scene(root, 1200, 700);
    stage.setScene(scene);
    scene.setFill(null);

    /*Stage*/
    stage.initStyle(StageStyle.TRANSPARENT);
    stage.centerOnScreen();
    stage.show();

}

有没有办法 reduce/eliminate 这种延迟?完全废弃预加载器并将它作为主程序中的一个阶段来实现会更好吗?提前致谢。

编辑:

我采纳了 Maverick283 的建议并实现了预加载器的淡出。仍然有一点延迟,所以我发送了最终通知(从主程序到预加载器) 显示主舞台之后,它完美地工作了!

public void start(Stage stage) {
    /*Scene*/
    scene = new Scene(root, 1200, 700);
    stage.setScene(scene);
    scene.setFill(null);

    /*Stage*/
    stage.initStyle(StageStyle.TRANSPARENT);
    stage.centerOnScreen();
    stage.show();
    notifyPreloader(new Preloader.ProgressNotification(0.99));
}

来自Oracle

The last state change notification received by the preloader before the application starts is StateChangeNotification.Type.BEFORE_START. After it is processed, the application's start() method is called. However, it can take time before the application is ready to display its stage after the start() method is called. If the preloader stage is already hidden, then there could be a period of time when the application shows nothing on the screen.

因此他们提供了如何解决该问题的示例代码:

@Override
public void handleStateChangeNotification(StateChangeNotification evt) {
    if (evt.getType() == StateChangeNotification.Type.BEFORE_START) {
        if (isEmbedded && stage.isShowing()) {
            //fade out, hide stage at the end of animation
            FadeTransition ft = new FadeTransition(
                Duration.millis(1000), stage.getScene().getRoot());
                ft.setFromValue(1.0);
                ft.setToValue(0.0);
                final Stage s = stage;
                EventHandler<ActionEvent> eh = new EventHandler<ActionEvent>() {
                    public void handle(ActionEvent t) {
                        s.hide();
                    }
                };
                ft.setOnFinished(eh);
                ft.play();
        } else {
            stage.hide();
        }
    }
}

如果您继续阅读,甚至可以共享两个阶段(预加载器和主应用程序阶段)...

我尝试了之前显示的解决方案但没有成功,然后我写了一个对我有用的代码,我所做的是让预加载器不被自己隐藏,它只是在显示主应用程序时隐藏,看:

预加载:

我评论了 stage.hide();

@Override
public void handleStateChangeNotification(StateChangeNotification scn) {
    if (scn.getType() == StateChangeNotification.Type.BEFORE_INIT) {
       //stage.hide();
    }
}

我把舞台设为静态

static Stage stage;

我添加了这段代码:

public static Stage getStage() {
    return stage;
}

在主应用上:

@Override
public void start(Stage stage) throws IOException {

    scene = new Scene(loadFXML("fxmlLoginGUI.fxml"), 640, 480);

    stage.setScene(scene);
    stage.show();
    if (stage.showingProperty().get()) {
        try {
            UkhuluvelaERP_Preloader.getStage().hide();
        } catch (Exception ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

我检查舞台是否已经显示,然后我使用 get 方法将预加载器舞台设置为 hide()。

我希望这对你们有用,就像对我一样。祝你好运。樱桃