Javafx exception when clicking TreeTableCell after repopulating TreeTableView

I am currently getting an error that I do not understand. The exception that is being thrown does not indicate anything to my code, but it is only thrown after I re-populate the TreeTableView by clearing the children of the root element and adding a new set of och children to it.

This is an 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)

      

Small MCVE (press "-" to repopulate the TreeTableView, then edit the cell to get an 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 the selection of TreeTableCells and this happens when selecting one after the first repopulation of the table. Otherwise, before re-settling, everything works as expected and no exceptions are thrown.

What is the problem? Are you not allowed to clear the children of the ObservableList in the TreeTableRoow, otherwise it must be done differently?

+3


source to share


1 answer


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

    }
}

      



+1


source







All Articles