Javafx exception when clicking TreeTableCell after repopulating TreeTableView

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-02 01:00:13

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!