Java fx tableview генерирует исключение нулевого указателя при установке новых элементов
У меня есть табличное представление, которое заполнено динамическими столбцами, которые я создаю в контроллере. В первый раз, когда я создаю таблицу, все работает нормально, но когда я пытаюсь перерисовать таблицу, используя новые элементы, я получаю исключение нулевого указателя, которое, кажется, вызвано некоторыми вложенными столбцами, которые я использую (из чтения трассировки стека). При перерисовке таблицы я делаю те же шаги, что и при первом ее создании:
Удалите все элементы (сначала используйте clear, затем используя remove all, чтобы быть уверенным)
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)
Наблюдаемая коллекция, устанавливаемая для таблицы, является наблюдаемым массивом и не имеет нулевых элементов. Я не знаю, что я пропустил в вышеуказанном процессе, пожалуйста, помогите спасибо
Обновление: это должно было показать, как работает мой код, мне не удалось воспроизвести ошибку в этом 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 ответ
Это похоже на известную ошибку.
Попробуйте выполнить обновление до последней версии Java 8 (или предварительной версии Java 8u20, если это не помогло).