3

I am trying to make a simple app that has 2 screens, one that loads the app, one that totals the prices of inputted items with just Java and CSS (no FXML), but I'm stuck on the splash screen. I know that this

primaryStage.initStyle(StageStyle.UNDECORATED);

gets rid of the buttons on top of the window from this post.

How to remove JavaFX stage buttons (minimize, maximize, close)

Once the splash screen closes (I have it set to close in 5 seconds), I want the 3 buttons to be visible to the user. So the obvious thing to do would be this.

PauseTransition delay = new PauseTransition(Duration.seconds(5));
delay.setOnFinished(e -> {
    primaryStage.setScene(mainScene);
    primaryStage.initStyle(StageStyle.DECORATED);
});
delay.play();

primaryStage.show();

But I get this stack trace:

Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Cannot set style once stage has been set visible
at javafx.stage.Stage.initStyle(Stage.java:493)
at splash.SplashScreen.lambda$0(SplashScreen.java:42)
at javafx.animation.Animation.impl_finished(Animation.java:1132)
at javafx.animation.AnimationAccessorImpl.finished(AnimationAccessorImpl.java:49)
at com.sun.scenario.animation.shared.SingleLoopClipEnvelope.timePulse(SingleLoopClipEnvelope.java:103)
at javafx.animation.Animation.impl_timePulse(Animation.java:1102)
at javafx.animation.Animation$1.lambda$timePulse$25(Animation.java:186)
at java.security.AccessController.doPrivileged(Native Method)
at javafx.animation.Animation$1.timePulse(Animation.java:185)
at com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:344)
at com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:506)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

I know that a splash screen isn't supposed to just wait n seconds then open the app, but that's not the point.

What strikes me most is the first line of the stack trace: "Cannot set style once stage has been set visible". Why can't I change the style? What prevents JavaFX from adding a bar and 3 buttons??

I've even tried doing this:

PauseTransition delay = new PauseTransition(Duration.seconds(5));
delay.setOnFinished(e -> {
    primaryStage.hide();
    primaryStage.setScene(mainScene);
    primaryStage.initStyle(StageStyle.DECORATED);
    primaryStage.show();
});
delay.play();

primaryStage.show();

in an effort to hide the window, change the initStyle, then show it, but I get the same error once more.

So again, my question is, why can't I change the style? What prevents JavaFX from adding a bar and 3 buttons??

I am thankful for any help.

Community
  • 1
  • 1
Alex Zhang
  • 123
  • 1
  • 10

1 Answers1

4

JavaFX can't add a bar and 3 buttons because it doesn't know how to. It doesn't even know that window decoration consists of those things. When the Stage is first made visible, JavaFX asks the Window Manager to create the window ("stage") and passes it some properties, such as size, position, type hint, window decoration etc. If window decoration was requested, then it is the Window Manager that draws your bar and 3 buttons. So if the exception wasn't thrown, then changing the decoration style would have no effect anyway as the window (without decoration) has already been created by the Window Manager. Changing this after the Window Manager is managing the window would require implementations for all the platforms on which JavaFX runs (if they support it).

And I think you can solve your individual problem just by using a second Stage.

Stage mainAppStage = new Stage();
mainAppStage.setScene(mainScene);

PauseTransition delay = new PauseTransition(Duration.seconds(5));
delay.setOnFinished(e -> {
    primaryStage.hide();
    mainAppStage.show();
});
delay.play();

primaryStage.show();
Poundex
  • 410
  • 4
  • 5
  • Haha thanks, you answered my question AND saved me hours of headaches! I always thought primaryStage was the only usable stage since it was the only parameter, but now I know I can use more than that one stage. I will now see if I can replicate it with FXML and a controller. – Alex Zhang Nov 24 '16 at 00:06
  • If you do end up using two stages you should swap them around, so your app goes in the primary stage and the splash screen goes in the throw-away stage – Poundex Nov 24 '16 at 19:20