Issue
Good day,
When I run this Code:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class mcve extends Application {
static Label myScore = new Label("Test");
static Rectangle rect = new Rectangle(0,0,10,10);
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
myScore.setTextFill(Color.WHITE);
myScore.setLayoutY(20);
myScore.setLayoutX(200);
myScore.setFont(new Font("Arial", 30));
myScore.setText("0");
rect.setFill(Color.WHITE);
final Group group = new Group(myScore,rect);
Scene scene = new Scene(group, 500, 500, Color.BLACK);
stage.setScene(scene);
stage.show();
}
}
it creates the following exception:
Exception in thread "main" java.lang.ExceptionInInitializerError
at mcve.<clinit>(mcve.java:11)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:122)
Caused by: java.lang.IllegalStateException: Toolkit not initialized
at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:273)
at com.sun.javafx.application.PlatformImpl.runLater(PlatformImpl.java:268)
at com.sun.javafx.application.PlatformImpl.setPlatformUserAgentStylesheet(PlatformImpl.java:550)
at com.sun.javafx.application.PlatformImpl.setDefaultPlatformUserAgentStylesheet(PlatformImpl.java:512)
at javafx.scene.control.Control.<clinit>(Control.java:87)
... 4 more
However if I remove the static keyword before Label at the top, the code runs just fine.
My question is: Why does the error occur when creating a static Label but not a static Rectangle? I want the Label to be static and not an object of a class.
Solution
Why does the error occur when creating a
static Label
but not astatic Rectangle
?
Essentially, this is a matter of initialization order. The UI platform needs to be properly initialized when creating Node
objects. Potentially, it could also happen with a Rectangle
, but most likely a Label
(which is a Control
) relies even more on a properly initialized platform. In this particular case, the difference is that Shape
objects do not require CSS
, while Control
objects do. This causes the platform methods to be called as seen in the stack trace, at a point when the toolkit is not yet initialized.
The
static
class member is initialized whenclass mvce
is loaded. This is done before themain()
method is called, and hence before thelaunch()
method is called. The platform is not initialized yet at this point.The non-static member, on the other side, is initialized when
class mvce
is instantiated. Theclass mvce
is instantiated internally by thelaunch()
method, after the toolkit has been properly initialized.
Also, there is usually no reason to use static references. Just use a member.
Answered By - Andreas Fester
Answer Checked By - David Goodson (JavaFixing Volunteer)