Take this slightly modified version of the Tree Table View example from the docs:
package prv.rli.codetest;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableColumn.CellDataFeatures;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
public class TreeTableViewSample extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) {
stage.setTitle("Tree Table View Samples");
final Scene scene = new Scene(new Group(), 200, 400);
Group sceneRoot = (Group)scene.getRoot();
//Creating tree items
final TreeItem<String> childNode1 = new TreeItem<>("Child Node 1");
final TreeItem<String> childNode2 = new TreeItem<>("Child Node 2");
childNode2.setExpanded(true);
final TreeItem<String> childNode3 = new TreeItem<>("Child Node 3");
//Creating the root element
final TreeItem<String> root = new TreeItem<>("Root node");
root.setExpanded(true);
//Adding tree items to the root
root.getChildren().setAll(childNode1, childNode2, childNode3);
//Creating a column
TreeTableColumn<String,String> column = new TreeTableColumn<>("Column");
column.setPrefWidth(150);
//Defining cell content
column.setCellValueFactory((CellDataFeatures<String, String> p) ->
new ReadOnlyStringWrapper(p.getValue().getValue()));
//Creating a tree table view
final TreeTableView<String> treeTableView = new TreeTableView<>(root);
treeTableView.getColumns().add(column);
treeTableView.setPrefWidth(152);
treeTableView.setShowRoot(false);
sceneRoot.getChildren().add(treeTableView);
stage.setScene(scene);
stage.show();
}
}
Run the example, click on Child Node 2, then press the arrow-left-button. The selection disappears.
Press the arrow-left-button again. An NPE appears:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at prv.rli.codetest.TreeTableViewSample.lambda$0(TreeTableViewSample.java:44)
at javafx.scene.control.TreeTableColumn.getCellObservableValue(TreeTableColumn.java:563)
at javafx.scene.control.TreeTableColumn.getCellObservableValue(TreeTableColumn.java:548)
at javafx.scene.control.TreeTableCell.updateItem(TreeTableCell.java:635)
at javafx.scene.control.TreeTableCell.indexChanged(TreeTableCell.java:457)
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
at com.sun.javafx.scene.control.skin.TableRowSkinBase.requestCellUpdate(TableRowSkinBase.java:659)
at com.sun.javafx.scene.control.skin.TableRowSkinBase.lambda$init$497(TableRowSkinBase.java:159)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:105)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.control.Cell.setItem(Cell.java:403)
at javafx.scene.control.Cell.updateItem(Cell.java:670)
at javafx.scene.control.TreeTableRow.updateItem(TreeTableRow.java:416)
at javafx.scene.control.TreeTableRow.indexChanged(TreeTableRow.java:291)
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1957)
at com.sun.javafx.scene.control.skin.VirtualFlow.addLeadingCells(VirtualFlow.java:1246)
at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1194)
at com.sun.javafx.scene.control.skin.VirtualFlow.setCellCount(VirtualFlow.java:231)
at com.sun.javafx.scene.control.skin.TreeTableViewSkin.updateRowCount(TreeTableViewSkin.java:486)
at com.sun.javafx.scene.control.skin.VirtualContainerBase.checkState(VirtualContainerBase.java:113)
at com.sun.javafx.scene.control.skin.VirtualContainerBase.layoutChildren(VirtualContainerBase.java:108)
at com.sun.javafx.scene.control.skin.TableViewSkinBase.layoutChildren(TableViewSkinBase.java:696)
at javafx.scene.control.Control.layoutChildren(Control.java:576)
at javafx.scene.control.TreeTableView.layoutChildren(TreeTableView.java:1468)
at javafx.scene.Parent.layout(Parent.java:1087)
at javafx.scene.Parent.layout(Parent.java:1093)
at javafx.scene.Scene.doLayoutPass(Scene.java:552)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2397)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)
at java.lang.Thread.run(Thread.java:745)
I think TreeViewBehavior.collapseRow(...) seems to be responsible for that. There should be another early-abort condition.
package prv.rli.codetest;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableColumn.CellDataFeatures;
import javafx.scene.control.TreeTableView;
import javafx.stage.Stage;
public class TreeTableViewSample extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) {
stage.setTitle("Tree Table View Samples");
final Scene scene = new Scene(new Group(), 200, 400);
Group sceneRoot = (Group)scene.getRoot();
//Creating tree items
final TreeItem<String> childNode1 = new TreeItem<>("Child Node 1");
final TreeItem<String> childNode2 = new TreeItem<>("Child Node 2");
childNode2.setExpanded(true);
final TreeItem<String> childNode3 = new TreeItem<>("Child Node 3");
//Creating the root element
final TreeItem<String> root = new TreeItem<>("Root node");
root.setExpanded(true);
//Adding tree items to the root
root.getChildren().setAll(childNode1, childNode2, childNode3);
//Creating a column
TreeTableColumn<String,String> column = new TreeTableColumn<>("Column");
column.setPrefWidth(150);
//Defining cell content
column.setCellValueFactory((CellDataFeatures<String, String> p) ->
new ReadOnlyStringWrapper(p.getValue().getValue()));
//Creating a tree table view
final TreeTableView<String> treeTableView = new TreeTableView<>(root);
treeTableView.getColumns().add(column);
treeTableView.setPrefWidth(152);
treeTableView.setShowRoot(false);
sceneRoot.getChildren().add(treeTableView);
stage.setScene(scene);
stage.show();
}
}
Run the example, click on Child Node 2, then press the arrow-left-button. The selection disappears.
Press the arrow-left-button again. An NPE appears:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at prv.rli.codetest.TreeTableViewSample.lambda$0(TreeTableViewSample.java:44)
at javafx.scene.control.TreeTableColumn.getCellObservableValue(TreeTableColumn.java:563)
at javafx.scene.control.TreeTableColumn.getCellObservableValue(TreeTableColumn.java:548)
at javafx.scene.control.TreeTableCell.updateItem(TreeTableCell.java:635)
at javafx.scene.control.TreeTableCell.indexChanged(TreeTableCell.java:457)
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
at com.sun.javafx.scene.control.skin.TableRowSkinBase.requestCellUpdate(TableRowSkinBase.java:659)
at com.sun.javafx.scene.control.skin.TableRowSkinBase.lambda$init$497(TableRowSkinBase.java:159)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:105)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.control.Cell.setItem(Cell.java:403)
at javafx.scene.control.Cell.updateItem(Cell.java:670)
at javafx.scene.control.TreeTableRow.updateItem(TreeTableRow.java:416)
at javafx.scene.control.TreeTableRow.indexChanged(TreeTableRow.java:291)
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1957)
at com.sun.javafx.scene.control.skin.VirtualFlow.addLeadingCells(VirtualFlow.java:1246)
at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1194)
at com.sun.javafx.scene.control.skin.VirtualFlow.setCellCount(VirtualFlow.java:231)
at com.sun.javafx.scene.control.skin.TreeTableViewSkin.updateRowCount(TreeTableViewSkin.java:486)
at com.sun.javafx.scene.control.skin.VirtualContainerBase.checkState(VirtualContainerBase.java:113)
at com.sun.javafx.scene.control.skin.VirtualContainerBase.layoutChildren(VirtualContainerBase.java:108)
at com.sun.javafx.scene.control.skin.TableViewSkinBase.layoutChildren(TableViewSkinBase.java:696)
at javafx.scene.control.Control.layoutChildren(Control.java:576)
at javafx.scene.control.TreeTableView.layoutChildren(TreeTableView.java:1468)
at javafx.scene.Parent.layout(Parent.java:1087)
at javafx.scene.Parent.layout(Parent.java:1093)
at javafx.scene.Scene.doLayoutPass(Scene.java:552)
at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2397)
at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139)
at java.lang.Thread.run(Thread.java:745)
I think TreeViewBehavior.collapseRow(...) seems to be responsible for that. There should be another early-abort condition.