JavaFX issue with static keyword; with Minimal, Co

2020-02-07 06:45发布

问题:

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.

回答1:

Why does the error occur when creating a static Label but not a static 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 when class mvce is loaded. This is done before the main() method is called, and hence before the launch() 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. The class mvce is instantiated internally by the launch() method, after the toolkit has been properly initialized.

Also, there is usually no reason to use static references. Just use a member.



回答2:

Have you tried to just declare the static label, but instanciate and set it later on in the start() method? This should work, too.