user3558582
user3558582

Reputation:

How to test if a tree item is the root node for the treeview in javafx?

I have been trying to prevent my program from deleting the root node of my tree view but when ever I try and do so my program gives me a "java.lang.reflect.InvocationTargetException" during its compiling and the program will not launch. I am not really sure why it will not launch.

Here is my TextFieldTreeCellImpl class where the error takes place:

private final class TextFieldTreeCellImpl extends TreeCell<String> {

    private TextField textField;
    private ContextMenu addMenu = new ContextMenu();


    public TextFieldTreeCellImpl() {
        MenuItem addMenuItem0 = new MenuItem("Add Folder");
        addMenu.getItems().add(addMenuItem0);
        addMenuItem0.setOnAction(new EventHandler<ActionEvent>() {
            public void handle(ActionEvent t) {
                TreeItem<String> newFolder = 
                    new TreeItem<String>("New Folder",new ImageView(depIcon));
                        getTreeItem().getChildren().add(newFolder);
            }
        });

        MenuItem addMenuItem1 = new MenuItem("Delete");
        addMenu.getItems().add(addMenuItem1);

        addMenuItem1.setOnAction(new EventHandler<ActionEvent>() {
            public void handle(ActionEvent t) {//There is not error when the if statement is in here
                        getTreeItem().getParent().getChildren().remove(getTreeItem());
                }
        });
        if(getTreeItem().getParent()==null){//The error is here-------------
             addMenuItem1.disableProperty().set(true);
        }
    }

    public void startEdit() {
        super.startEdit();

        if (textField == null) {
            createTextField();
        }
        setText(null);
        setGraphic(textField);
        textField.selectAll();
    }

    public void cancelEdit() {
        super.cancelEdit();

        setText((String) getItem());
        setGraphic(getTreeItem().getGraphic());
    }


    public void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);

        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            if (isEditing()) {
                if (textField != null) {
                    textField.setText(getString());
                }
                setText(null);
                setGraphic(textField);
            } else {
                setText(getString());
                setGraphic(getTreeItem().getGraphic());
                    setContextMenu(addMenu);
            }
        }
    }

    private void createTextField() {
        textField = new TextField(getString());
        textField.setOnKeyReleased(new EventHandler<KeyEvent>() {

            public void handle(KeyEvent t) {
                if (t.getCode() == KeyCode.ENTER) {
                    commitEdit(textField.getText());
                } else if (t.getCode() == KeyCode.ESCAPE) {
                    cancelEdit();
                }
            }
        });  

    }

    private String getString() {
        return getItem() == null ? "" : getItem().toString();
    }
}
}

Here is the error I get:

Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$147(Unknown Source)
at com.sun.javafx.application.LauncherImpl$$Lambda$48/128893786.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at application.CopyOfMain$TextFieldTreeCellImpl.<init>(CopyOfMain.java:82)
at application.CopyOfMain$1.call(CopyOfMain.java:48)
at application.CopyOfMain$1.call(CopyOfMain.java:1)
at com.sun.javafx.scene.control.skin.TreeViewSkin.createCell(Unknown Source)
at com.sun.javafx.scene.control.skin.TreeViewSkin.lambda$new$513(Unknown Source)
at com.sun.javafx.scene.control.skin.TreeViewSkin$$Lambda$115/979660402.call(Unknown Source)
at com.sun.javafx.scene.control.skin.VirtualFlow.getCell(Unknown Source)
at com.sun.javafx.scene.control.skin.VirtualFlow.getCellLength(Unknown Source)
at com.sun.javafx.scene.control.skin.VirtualFlow.computeViewportOffset(Unknown Source)
at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(Unknown Source)
at javafx.scene.Parent.layout(Unknown Source)
at javafx.scene.Parent.layout(Unknown Source)
at javafx.scene.Parent.layout(Unknown Source)
at javafx.scene.Scene.doLayoutPass(Unknown Source)
at javafx.scene.Scene.preferredSize(Unknown Source)
at javafx.scene.Scene.impl_preferredSize(Unknown Source)
at javafx.stage.Window$9.invalidated(Unknown Source)
at javafx.beans.property.BooleanPropertyBase.markInvalid(Unknown Source)
at javafx.beans.property.BooleanPropertyBase.set(Unknown Source)
at javafx.stage.Window.setShowing(Unknown Source)
at javafx.stage.Window.show(Unknown Source)
at javafx.stage.Stage.show(Unknown Source)
at application.CopyOfMain.start(CopyOfMain.java:54)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(Unknown Source)
at com.sun.javafx.application.LauncherImpl$$Lambda$57/1520696636.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$44/1051754451.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$164(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/1933975749.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$46/1775282465.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$141(Unknown Source)
at com.sun.glass.ui.win.WinApplication$$Lambda$37/1109371569.run(Unknown Source)
... 1 more
Exception running application application.CopyOfMain

And here is my Main Class although I do not think that it is realavent:

public class Main extends Application {

private final Node rootIcon = 
    new ImageView(new Image(getClass().getResourceAsStream("folder.jpg")));
private final Image depIcon = 
    new Image(getClass().getResourceAsStream("folder.jpg"));

TreeItem<String> rootNode = 
    new TreeItem<String>("Resources", rootIcon);

public static void main(String[] args) {
    Application.launch(args);
}

public void start(Stage stage) {
    rootNode.setExpanded(true); 
    stage.setTitle("Tree View Sample");
    VBox box = new VBox();
    final Scene scene = new Scene(box, 400, 300);
    scene.setFill(Color.LIGHTGRAY);

    TreeView<String> treeView = new TreeView<String>(rootNode);
    treeView.setEditable(true);
    treeView.setCellFactory(new Callback<TreeView<String>,TreeCell<String>>(){
        public TreeCell<String> call(TreeView<String> p) {
            return new TextFieldTreeCellImpl();
        }
    });

    box.getChildren().add(treeView);
    stage.setScene(scene);
    stage.show();
}

One thing that I did notice is that if I put the if statment in one of the handle methods there is no error.

Upvotes: 0

Views: 2169

Answers (1)

OttPrime
OttPrime

Reputation: 1938

At the time that the TextFieldTreeCellImpl object is constructed, there isn't a TreeItem associated to it. That typically happens shortly after construction and outside of your control. Regardless, the call to getTreeItem() is returning null and so the chained called to getParent() is then causing the NPE. The reason it works when you move it inside the handler is because that code is only called when an event is triggered (i.e. clicking on addMenuItem1) and by that time, the treeItem is populated in the cell.

I would add another EventHandler for the onShowing event of the ContextMenu and put the check and set inside of there. See the example in the docs: ContextMenu Javadoc

Upvotes: 2

Related Questions