问题
I am currently getting an error that I do not understand. The exception that is thrown points to nothing in my code, yet it is only thrown after I repopulate a TreeTableView by clearing the root item's children and adding a new set och children to it.
This is the exception:
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)
A small MCVE (press "-" in order to repopulate the TreeTableView, then edit a cell to get the 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<String> table;
private TreeItem<String> 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<KeyEvent>() {
@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<String, String> column = new TreeTableColumn<String, String>("String");
column.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<String, String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(CellDataFeatures<String, String> param) {
// TODO Auto-generated method stub
return param.getValue().valueProperty();
}
});
column.setCellFactory(TextFieldTreeTableCell.forTreeTableColumn());
column.setOnEditCommit(new EventHandler<TreeTableColumn.CellEditEvent<String, String>>() {
@Override
public void handle(CellEditEvent<String, String> 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<String> treeItem = new TreeItem<String>(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");
}
}
I understand that the error is related to selecting TreeTableCells, and it occurs when selecting one after first repopulating the table. Otherwise, before repopulating, everything works as expected, and no exceptions are thrown whatsoever.
What is the problem? Are you not allowed to clear the children ObservableList in the TreeTableRoow, or should it be done in another way?
回答1:
private void populate() {
root.getChildren().clear()
for (int i = 1; i <= 10; i++) {
String string = "String " + i;
TreeItem<String> treeItem = new TreeItem<String>(string);
root.getChildren().add(treeItem);
// --------------Clear the selection -------------
table.getSelectionModel().clearSelection();
// -----------------------------------------------
}
}
来源:https://stackoverflow.com/questions/27830075/javafx-exception-when-clicking-treetablecell-after-repopulating-treetableview