Issue
I understand this may be a duplicate post. I will link what I've been looking as some of the sources may be wrong for this specific project.
Long story short, I'm making a game and just switched from JavaSwing to JavaFX. Currently right now, I'm making the start screen and making an attempt to try and make the screen fade out and clear itself out for the game to start. Using VBox
and HBox
, everything seems to be working kind of.
public static void fadeOut() {
FadeTransition ft = new FadeTransition(Duration.millis(3000), vb);
ft.setFromValue(1);
ft.setToValue(0);
ft.play();
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
Ce.console.getChildren().clear();
}
}, 300l);
startTrue();
}
As of right now, the start screen fades away but doesn't clear itself from the main VBox
and assuming I set up Timer()
wrong, I get this error.
Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
at [email protected]/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:297)
at [email protected]/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:458)
at [email protected]/javafx.scene.Parent$3.onProposedChange(Parent.java:474)
at [email protected]/com.sun.javafx.collections.VetoableListDecorator.clear(VetoableListDecorator.java:293)
at FXConsole/application.console.SS$1.run(SS.java:100)
at java.base/java.util.TimerThread.mainLoop(Timer.java:566)
at java.base/java.util.TimerThread.run(Timer.java:516)
I'm thinking that I'm supposed to be using an AnimationTimer()
/Timeline()
with KeyFrame()
but I'm not sure. I'll give it more testing and see if I can come to a solution but if anyone knows a better way to approach this, the help would be greatly appreciated.
edit: Here was the main page I used for this - How to set a Timer in Java?
sorry for the inconvenience.
Solution
You shouldn't be using a timer here.
If you want to do something when an animation like a transition finishes, then invoke animation.setOnFinished(eventHandler)
.
For your example:
FadeTransition ft = new FadeTransition(Duration.millis(3000), vb);
ft.setFromValue(1);
ft.setToValue(0);
ft.setOnFinished(e -> Ce.console.getChildren().clear());
ft.play();
Why your Timer usage fails
The error message you get when you use a timer:
IllegalStateException: Not on FX application thread
happens because the timer runs on its own thread and you should not modify the scene graph from another thread.
The IllegalStateException
error can be fixed by wrapping the code that executes in the timer in Platform.runLater(runnable)
. If you use runLater
, you need to ensure that any code executed via runLater
is not long-running code or IO that would block the JavaFX thread.
However, using the in-built onFinished
method is superior for numerous reasons, among them being that the onFinished
handler is always run on the JavaFX thread, so you don't need to deal with potentially complicated and error-prone multi-threaded code.
Answered By - jewelsea
Answer Checked By - Robin (JavaFixing Admin)