3

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?

  • Can you post an [MCVE](http://stackoverflow.com/help/mcve) – James_D Jan 08 '15 at 00:15
  • I have added a really small example now @James_D. Press "-" in order to repopulate the TreeTableView. Cell editing works before, but selecting a cell after repopulating will throw the exception above. – Peter Jonsson Jan 08 '15 at 16:26
  • 1
    worksforme (replaced substract by F1, though, not being at my desktop) in 8u40b15 There have been quite a number of bugs fixed since 8u20, might be related to one of them? – kleopatra Jan 08 '15 at 16:42
  • It's compiled with 8u25. That could be the problem. My client also runs 8u25 will the client also be forced to update to an early access build, or is it just a compiler related problem? – Peter Jonsson Jan 08 '15 at 17:19
  • 1
    Ah, ok, it fails with 8u25. Interestingly, it runs fine in either 8u20 or 8u40. I'm pretty certain it's a runtime issue, not a compile-time issue. – James_D Jan 08 '15 at 17:52
  • Thank you for your support. It works fine in 8u40. I guess that I will just have to instruct my client to download an early access version of Java until it is released. – Peter Jonsson Jan 08 '15 at 18:15

1 Answers1

2
    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();
        // -----------------------------------------------

    }
}
lola
  • 36
  • 2