重新填充TreeTableView后单击TreeTableCell时出现Javafxexception

我目前收到一个我不明白的错误。 抛出的exception在我的代码中指向任何内容,但只有在我通过清除根项目的子项并向其添加新的set och子项重新填充TreeTableView之后才抛出它。

这是例外:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.handleSelectedCellsListChangeEvent(TreeTableView.java:3056) at javafx.scene.control.TreeTableView$TreeTableViewArrayListSelectionModel.clearAndSelect(TreeTableView.java:2527) at com.sun.javafx.scene.control.behavior.TableCellBehaviorBase.simpleSelect(TableCellBehaviorBase.java:209) at com.sun.javafx.scene.control.behavior.TableCellBehaviorBase.doSelect(TableCellBehaviorBase.java:148) at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(CellBehaviorBase.java:132) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:95) at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89) at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) at javafx.event.Event.fireEvent(Event.java:198) at javafx.scene.Scene$MouseHandler.process(Scene.java:3724) at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3452) at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1728) at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2461) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:348) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:273) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:382) at com.sun.glass.ui.View.handleMouseEvent(View.java:553) at com.sun.glass.ui.View.notifyMouse(View.java:925) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$141(WinApplication.java:102) at com.sun.glass.ui.win.WinApplication$$Lambda$37/1798286609.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) 

一个小的MCVE(按“ – ”以重新填充TreeTableView,然后编辑一个单元格以获得exception):

 package test; import javafx.application.Application; import javafx.beans.value.ObservableValue; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.TitledPane; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeTableColumn; import javafx.scene.control.TreeTableColumn.CellDataFeatures; import javafx.scene.control.TreeTableColumn.CellEditEvent; import javafx.scene.control.TreeTableView; import javafx.scene.control.cell.TextFieldTreeTableCell; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.stage.Stage; import javafx.util.Callback; public class BillingTableTest extends Application { private Stage stage; private Scene scene; private TitledPane pane; private TreeTableView table; private TreeItem root; /** * Start the program from scratch. * * @param args * Input arguments. Leave empty. */ public static void main(String[] args) { launch(args); } /** * Start the program. Not usually called by the user, but by JavaFX. Nothing * fancy here, but setting up a basic TreeTableView with one column. */ public void start(Stage stage) { this.stage = stage; pane = new TitledPane(); scene = new Scene(pane); pane.setOnKeyReleased(new EventHandler() { @Override public void handle(KeyEvent event) { // TODO Auto-generated method stub if (event.getCode() == KeyCode.SUBTRACT) { repopulate(); } } }); table = new TreeTableView(); root = new TreeItem("Root"); root.setExpanded(true); table.setRoot(root); table.setShowRoot(false); table.setEditable(true); TreeTableColumn column = new TreeTableColumn("String"); column.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures, ObservableValue>() { @Override public ObservableValue call(CellDataFeatures param) { // TODO Auto-generated method stub return param.getValue().valueProperty(); } }); column.setCellFactory(TextFieldTreeTableCell.forTreeTableColumn()); column.setOnEditCommit(new EventHandler<TreeTableColumn.CellEditEvent>() { @Override public void handle(CellEditEvent t) { t.getTreeTablePosition().getTreeItem().setValue(t.getNewValue()); } }); table.getColumns().add(column); populate(); pane.setContent(table); stage.setScene(scene); stage.show(); System.out.println("TreeTableView has not been repopulated. Editing will not throw an exception."); System.out.println("Press - to repopulate it and break it."); } /** * Populate the TreeTableView with some dummy data. */ private void populate() { for (int i = 1; i <= 10; i++) { String string = "String " + i; TreeItem treeItem = new TreeItem(string); root.getChildren().add(treeItem); } } /** * Clear root children (clears the TreeTableView). Cell editing is most * likely broken by this. */ private void clear() { root.getChildren().clear(); // <- Most likely the problem. } /** * Repopulate the root node (repopulate the TreeTableView). After this * method is called, cell editing will throw an excetion. */ private void repopulate() { clear(); // <- Most likely the problem. populate(); System.out.println("TreeTableView has been repopulated. Editing will now throw an exception"); } } 

我知道错误与选择TreeTableCells有关,并且在首次重新填充表格后选择一个时会发生错误。 否则,在重新填充之前,一切都按预期工作,并且不会抛出任何exception。

问题是什么? 您是否不允许清除TreeTableRoow中的子ObservableList,还是应该以其他方式完成?

  private void populate() { root.getChildren().clear() for (int i = 1; i <= 10; i++) { String string = "String " + i; TreeItem treeItem = new TreeItem(string); root.getChildren().add(treeItem); // --------------Clear the selection ------------- table.getSelectionModel().clearSelection(); // ----------------------------------------------- } }