设置新项时,Java fx tableview会抛出空指针异常

时间:2014-08-04 16:41:29

标签: java javafx javafx-8

我有一个表视图,其中填充了我在控制器中创建的动态列。 我第一次创建表时一切正常,但是当我尝试使用新项重绘表时,我得到一个空指针异常,这似乎是由我使用的一些嵌套列引起的(从读取堆栈跟踪)。重新绘制表格时,我采取了与第一次创建时相同的步骤:

删除所有商品(首先使用清除,然后使用全部删除,只是为了确保)

tableFullTimetable.getItems().clear();
tableFullTimetable.getItems().removeAll();

删除所有列(与列相同)

tableFullTimetable.getColumns().clear();
tableFullTimetable.getColumns().removeAll();

然后我使用for循环添加动态嵌套列,然后在表上设置新项

tableFullTimetable.setItems(myNewItems);

我理解表视图有刷新问题,但我认为这是不同的,表被清除但是当执行到达设置行时它会抛出空指针异常,这里是错误的堆栈跟踪:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at com.sun.javafx.scene.control.skin.NestedTableColumnHeader.dispose(NestedTableColumnHeader.java:323)
    at com.sun.javafx.scene.control.skin.NestedTableColumnHeader.updateTableColumnHeaders(NestedTableColumnHeader.java:265)
    at com.sun.javafx.scene.control.skin.NestedTableColumnHeader.checkState(NestedTableColumnHeader.java:519)
    at com.sun.javafx.scene.control.skin.NestedTableColumnHeader.computePrefHeight(NestedTableColumnHeader.java:401)
    at javafx.scene.Parent.prefHeight(Parent.java:918)
    at javafx.scene.layout.Region.prefHeight(Region.java:1438)
    at com.sun.javafx.scene.control.skin.TableHeaderRow.computePrefHeight(TableHeaderRow.java:344)
    at com.sun.javafx.scene.control.skin.TableHeaderRow.computeMinHeight(TableHeaderRow.java:339)
    at javafx.scene.Parent.minHeight(Parent.java:946)
    at javafx.scene.layout.Region.minHeight(Region.java:1404)
    at javafx.scene.control.SkinBase.computeMinHeight(SkinBase.java:254)
    at javafx.scene.control.Control.computeMinHeight(Control.java:485)
    at javafx.scene.Parent.minHeight(Parent.java:946)
    at javafx.scene.layout.Region.minHeight(Region.java:1404)
    at javafx.scene.layout.Region.computeChildMinAreaHeight(Region.java:1700)
    at javafx.scene.layout.BorderPane.getAreaHeight(BorderPane.java:618)
    at javafx.scene.layout.BorderPane.computeMinHeight(BorderPane.java:415)
    at javafx.scene.Parent.minHeight(Parent.java:946)
    at javafx.scene.layout.Region.minHeight(Region.java:1404)
    at javafx.scene.layout.Region.boundedNodeSizeWithBias(Region.java:1920)
    at javafx.scene.layout.Region.layoutInArea(Region.java:2326)
    at javafx.scene.layout.Region.layoutInArea(Region.java:2241)
    at javafx.scene.layout.Region.layoutInArea(Region.java:2182)
    at javafx.scene.layout.StackPane.layoutChildren(StackPane.java:351)
    at javafx.scene.Parent.layout(Parent.java:1076)
    at javafx.scene.Parent.layout(Parent.java:1082)
    at javafx.scene.Parent.layout(Parent.java:1082)
    at javafx.scene.Scene.doLayoutPass(Scene.java:576)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2386)
    at com.sun.javafx.tk.Toolkit$3.run(Toolkit.java:321)
    at com.sun.javafx.tk.Toolkit$3.run(Toolkit.java:319)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:319)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:348)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:479)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:460)
    at com.sun.javafx.tk.quantum.QuantumToolkit$13.run(QuantumToolkit.java:327)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
    at com.sun.glass.ui.win.WinApplication$4$1.run(WinApplication.java:112)
    at java.lang.Thread.run(Thread.java:745)

设置到表的可观察集合是一个可观察的arraylist,它没有任何null项。我不知道在上述过程中我错过了什么,请帮助谢谢

更新 这是为了说明我的代码是如何工作的,我没有成功再现这个MCVE中的错误,但我希望它可以帮助你帮助我:)

public class TestTable extends Application {

    private TableView<ERoom> tableFullTimetable = new TableView<>();
    private String[] days = {"monday", "tuesday", "wednesday", "thursday", "friday"};
    private Integer[] timeslots = {1, 2, 3, 4, 5};
    private List<ERoom> eRooms;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        VBox rootlayout = new VBox();
        primaryStage.setWidth(895);
        primaryStage.setHeight(550);
        primaryStage.setScene(new Scene(rootlayout));
        primaryStage.show();

        eRooms = new ArrayList<>();
        eRooms.add(new ERoom("room1"));
        eRooms.add(new ERoom("room2"));

        List<ELesson> eLessons = new ArrayList<>();
        eLessons.add(new ELesson(2, "friday", eRooms.get(0)));
        eLessons.add(new ELesson(4, "wednesday", eRooms.get(1)));
        eLessons.add(new ELesson(5, "monday", eRooms.get(1)));
        eLessons.add(new ELesson(1, "tuesday", eRooms.get(0)));
        eLessons.add(new ELesson(3, "thursday", eRooms.get(1)));
        ETimetable firstTimetable = new ETimetable(eLessons, eRooms);
        //Load the first timetable
        setTimeTable(firstTimetable);

        //Button for loading a different timetable
        Button button = new Button("Load second timetable");
        rootlayout.getChildren().add(tableFullTimetable);
        button.onActionProperty().addListener(new ChangeListener<EventHandler<ActionEvent>>() {
            @Override
            public void changed(ObservableValue<? extends EventHandler<ActionEvent>> observable, EventHandler<ActionEvent> oldValue, EventHandler<ActionEvent> newValue) {
                List<ELesson> othereLessons = new ArrayList<>();
                othereLessons.add(new ELesson(3, "tuesday", eRooms.get(0)));
                othereLessons.add(new ELesson(4, "monday", eRooms.get(1)));
                othereLessons.add(new ELesson(2, "friday", eRooms.get(1)));
                othereLessons.add(new ELesson(5, "wednesday", eRooms.get(0)));
                ETimetable secondtimetable = new ETimetable(othereLessons, eRooms);
                setTimeTable(secondtimetable);
            }
        });
        rootlayout.getChildren().add(button);
    }

    private void setTimeTable(ETimetable newtimetable) {
        if (tableFullTimetable.getItems() != null) {
            tableFullTimetable.getItems().clear();
            tableFullTimetable.getItems().removeAll();
        }
        if (tableFullTimetable.getColumns() != null) {
            tableFullTimetable.getColumns().clear();
            tableFullTimetable.getColumns().removeAll();
        }
        //Nested loops for creating columns
        for (String day : days) {
            TableColumn dayTableColumn = new TableColumn(day);
            tableFullTimetable.getColumns().add(dayTableColumn);
            for (int timeslot : timeslots) {
                TableColumn<ERoom, ELesson> timeslotTableColumn = new TableColumn<>(Integer.toString(timeslot));
                timeslotTableColumn.setPrefWidth(50);
                timeslotTableColumn.setCellValueFactory(param -> {
                    for (ELesson lesson : newtimetable.getLessons()) {
                        //Return the lesson that matches this column's room and day+timeslot
                        if (lesson.getRoom().equals(param.getValue()) && lesson.getDay().equals(day) && lesson.getTimeslot() == timeslot) {
                            return new ReadOnlyObjectWrapper<ELesson>(lesson);
                        }
                    }
                    return null;
                });
                dayTableColumn.getColumns().add(timeslotTableColumn);
            }
        }
        //This is where it fails
        tableFullTimetable.setItems(FXCollections.observableArrayList(newtimetable.getRooms()));
    }

    private class ETimetable {
        private List<ELesson> lessons;
        private List<ERoom> rooms;

        private ETimetable(List<ELesson> lessons, List<ERoom> rooms) {
            this.lessons = lessons;
            this.rooms = rooms;
        }

        public List<ELesson> getLessons() {
            return lessons;
        }

        public List<ERoom> getRooms() {
            return rooms;
        }
    }

    private class ELesson {
        private int timeslot;
        private String day;
        private ERoom room;

        private ELesson(int timeslot, String day, ERoom room) {
            this.timeslot = timeslot;
            this.day = day;
            this.room = room;
        }

        public int getTimeslot() {
            return timeslot;
        }

        public String getDay() {
            return day;
        }

        public ERoom getRoom() {
            return room;
        }

        @Override
        public String toString() {
            return day + " at " + timeslot + " in " + room.getName();
        }
    }

    private class ERoom {
        String name;

        private ERoom(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}

1 个答案:

答案 0 :(得分:3)

这看起来像known bug

尝试更新到Java 8的最新版本(或Java 8u20的预发行版,如果它没有修复它)。