Java fx tableview在设置新项时引发空指针异常

Java fx tableview在设置新项时引发空指针异常,java,javafx,javafx-8,Java,Javafx,Javafx 8,我有一个表视图,其中填充了我在控制器中创建的动态列。 第一次创建表时,一切正常,但是当我尝试使用新项重新绘制表时,我得到一个空指针异常,这似乎是由我使用的一些嵌套列(从读取堆栈跟踪中)引起的。重新绘制表格时,我采取了与第一次创建表格时相同的步骤,包括: 删除所有项目(首先使用清除,然后使用全部删除,以确保) 删除所有列(与列相同) 然后使用for循环添加动态嵌套列,然后在表上设置新项 tableFullTimetable.setItems(myNewItems); 我知道表视图有刷新问题,但我

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

删除所有项目(首先使用清除,然后使用全部删除,以确保)

删除所有列(与列相同)

然后使用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,它没有任何空项。我不知道在上述过程中我错过了什么,请帮助我,谢谢

更新: 这是为了展示我的代码是如何工作的,我还没有成功地重现这个MCVE中的错误,但我希望它能帮助您帮助我:)

公共类TestTable扩展应用程序{
private TableView tablefulltimeline=new TableView();
私有字符串[]天={“星期一”、“星期二”、“星期三”、“星期四”、“星期五”};
私有整数[]时隙={1,2,3,4,5};
私有列表eRoom;
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
公共无效开始(阶段primaryStage){
VBox rootlayout=新的VBox();
初生阶段,坐骨宽度(895);
初生阶段,坐骨高度(550);
primaryStage.setScene(新场景(rootlayout));
primaryStage.show();
eRoom=新的ArrayList();
添加(新ERoom(“room1”);
添加(新ERoom(“room2”);
List eLessons=new ArrayList();
添加(新的ELesson(2,“星期五”,eRooms.get(0));
添加(新的ELesson(4,“星期三”,eRooms.get(1));
添加(新ELesson(5,“星期一”,eRooms.get(1));
添加(新的ELesson(1,“星期二”,eRooms.get(0));
添加(新的ELesson(3,“星期四”,eRooms.get(1));
ETimetable FirstTimeline=新的ETimetable(Elesson、eRoom);
//加载第一个时间表
设定时间表(第一时间表);
//用于加载不同时间表的按钮
按钮按钮=新按钮(“加载第二个时间表”);
rootlayout.getChildren().add(tablefulltimeline);
button.onActionProperty().addListener(新的ChangeListener()){
@凌驾
公共空间改变(ObservalEvalue这看起来像一个


尝试更新到最新版本的Java 8(或Java 8u20的预发行版,如果这不能解决问题)。

您可能需要发布一篇文章来获得帮助。我已经做了很多次类似的事情,没有任何问题。另外,请注意,在
ObservableList
上调用
removeAll()
,并且不传递任何参数都不会产生任何效果(它将删除作为参数传入的所有值)。
clear()
是您想要的方法。谢谢,我认为它在内部过载了。我将尝试发布一些代码尝试先更新您的JDK;我认为这应该可以解决它。我添加了一个MCVE,它不会出于某种原因再现错误,但它显示了我的意图。我正在使用Java 8u5,让我更新到最新版本,看看它是如何运行的。再次感谢您的帮助。我也收到了相同的错误并进行了更新。但它不会改变任何内容:/
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)
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;
        }
    }
}