Unexplained NullPointerException in JavaFX applica

2019-08-25 18:46发布

问题:

Background Information

Creating a JavaFX application for Computer Science

What I'm doing

I call a class and open a scene that is created in the class

What is happening

I get a NullPointerException stacktrace; see below.

What I've tried

I used to print statements to see where it happens. It doesn't happen where the class is created, but in the class itself, it survives like the first two lines of code in the constructor.

Error

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at com.sun.javafx.scene.input.PickResultChooser.processOffer(PickResultChooser.java:185)
at com.sun.javafx.scene.input.PickResultChooser.offer(PickResultChooser.java:143)
at javafx.scene.Node.impl_intersects(Node.java:4945)
at javafx.scene.layout.Region.impl_pickNodeLocal(Region.java:2942)
at javafx.scene.Node.impl_pickNode(Node.java:4914)
at javafx.scene.Scene$MouseHandler.pickNode(Scene.java:3899)
at javafx.scene.Scene$MouseHandler.access$1600(Scene.java:3485)
at javafx.scene.Scene.pick(Scene.java:1942)
at javafx.scene.Scene.access$6700(Scene.java:159)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3711)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Unknown Source)

This stacktrace is repeated before the application crashes.

My code

public class StudentClassView {

    Scene back, scene;
    Stage window;

    public StudentClassView(Classroom classRoom, String student, Scene back, Stage window) {

        // Prepare Interface
        this.back = back;
        this.window = window;

        // Generate content
        String title_s;
        if (classRoom.getCourseAverage() != 0) {
            title_s = classRoom.getCode() + ", " + classRoom.getCourseAverage() + "%";
        } else {
            title_s = classRoom.getCode();
        }
        Label title = new Label(title_s);

        ArrayList<Label> assignments = new ArrayList<Label>();
        ArrayList<Label> scores = new ArrayList<Label>();
        if (classRoom.getAssignments() != null) {
            for (Assignment a : classRoom.getAssignments()) {
                assignments.add(new Label(a.getName()));
                String scoreEntry = a.getScore(student) + " (worth " + a.getWeight() + "%)";
                scores.add(new Label(scoreEntry));
            }
        }

        Button exit_b = new Button("Back");

        // Design layout
        ScrollPane layout = new ScrollPane();
        VBox content = new VBox();
        GridPane grid = new GridPane();
        int ind = 0;
        for (Label a : assignments) {
            grid.add(a, 0, ind);
            ind += 1;
        }
        ind = 0;
        for (Label s : scores) {
            grid.add(s, 1, ind);
            ind += 1;
        }
        content.getChildren().addAll(title, grid, exit_b);
        layout.setContent(layout);
        // Create Interface
        scene = new Scene(layout, 800, 600);

        // Handle events
        exit_b.setOnAction(e->{
            window.setScene(back);
        });

    }

    public Scene getScene() {
        return scene;
    }

}

回答1:

You should not use the ScrollPane (or any of it's ancestors) as it's content node. Change

layout.setContent(layout);

to something like

layout.setContent(content);

Otherwise when the skin of ScrollPane is created during the first layout a circle is created in the scene hierarchy which breaks JavaFX.