问题
I have a program that uses a simple preloader while the init()
method creates the main gui. Everything works fine but after the init()
method completes and the preloader disappears, there's a noticeable delay before the main stage shows up. I say noticeable because it can be as much as 7 seconds, enough for a user to get confused.
I tried to put as little as possible in the start()
method:
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();
}
Is there a way to reduce/eliminate this delay? Would it be better to scrap the preloader altogether and implement is as a stage in the main program? Thanks in advance.
EDIT:
I took Maverick283's advice and implemented a fadeOut of the preloader. There was still a bit of delay so I sent the final notification (from the main program to the preloader) after showing the main stage and it worked perfectly!
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));
}
回答1:
From 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.
Thus they provide example code how to fix that:
@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();
}
}
}
If you continue reading there is even a way of sharing the two stages (preloader and main application stage)...
回答2:
I tried the solution shown before but not worked, then I wrote a code that worked for me, what I did was make the preloader dont be hiden by itself, it just get hided when the main app is shown, look:
On Preload:
I commented the stage.hide();
@Override
public void handleStateChangeNotification(StateChangeNotification scn) {
if (scn.getType() == StateChangeNotification.Type.BEFORE_INIT) {
//stage.hide();
}
}
I set stage as static
static Stage stage;
I added this code:
public static Stage getStage() {
return stage;
}
On main app:
@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);
}
}
}
I check if the stage is already shown, then I set the preloader stage to hide() using a get method.
I hope this works for you guys as did for me. good luck. chers
来源:https://stackoverflow.com/questions/36642408/delay-between-preloader-and-stage-shown