Search code examples
treeviewjavafx-2right-click

right click menu option in the tree root node


I want right click menu option in the tree root node(JavaFX). Could any one help me on this.

TreeItem<String> root = new TreeItem<>(""+selectedDirectory);
root.setExpanded(true);

locationTreeView.setRoot(root);

root.getChildren().addAll(
    new TreeItem<>("Item 1"),
    new TreeItem<>("Item 2"),
    new TreeItem<>("Item 3")
);

Solution

  • You can perform the desired behaviour in two steps:

    1. Defining a custom TreeCell factory on your TreeView;
    2. Attaching a context menu on the TreeCell of the root tree item.

    The following code defines the custom TreeCell factory:

    // defines a custom tree cell factory for the tree view
    tree.setCellFactory(new Callback<TreeView<String>, TreeCell<String>>() {
    
        @Override
        public TreeCell<String> call(TreeView<String> arg0) {
            // custom tree cell that defines a context menu for the root tree item
            return new MyTreeCell();
        }
    });
    

    And, here is the implementation of a custom tree cell that attaches a context menu for the root tree item:

    class MyTreeCell extends TextFieldTreeCell<String> {
        private ContextMenu rootContextMenu;
    
        public MyTreeCell() {
            // instantiate the root context menu
            rootContextMenu = 
                ContextMenuBuilder.create()
                    .items(
                            MenuItemBuilder.create()
                                .text("Menu Item")
                                .onAction(
                                    new EventHandler<ActionEvent>() {
                                        @Override
                                        public void handle(ActionEvent arg0) {
                                            System.out.println("Menu Item Clicked!");                                           
                                        }
                                    }
                                )
                                .build()
                        )
                    .build();
        }
    
        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
    
            // if the item is not empty and is a root...
            if (!empty && getTreeItem().getParent() == null) {
                setContextMenu(rootContextMenu);
            }
        }
    }
    

    The following example ilustrates the use of both, cell factory and custom cell, together:

    public class TreeViewWithContextMenuOnRoot extends Application {
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage primaryStage) {
            primaryStage.setTitle("Tree with context menu on root");        
    
            TreeItem<String> rootItem = new TreeItem<String> ("Tree root");
            rootItem.setExpanded(true);
            for (int i = 1; i < 3; i++) {
                TreeItem<String> item = new TreeItem<String> ("item" + i);            
                rootItem.getChildren().add(item);
            }        
            final TreeView<String> tree = new TreeView<String> ();   
    
            tree.setRoot(rootItem);
    
            // defines a custom tree cell factory for the tree view
            tree.setCellFactory(new Callback<TreeView<String>, TreeCell<String>>() {
    
                @Override
                public TreeCell<String> call(TreeView<String> arg0) {
                    // custom tree cell that defines a context menu for the root tree item
                    return new MyTreeCell();
                }
            });
    
            StackPane root = new StackPane();
            root.getChildren().add(tree);
            primaryStage.setScene(new Scene(root, 200, 100));
            primaryStage.show();
        }
    
        private static class MyTreeCell extends TextFieldTreeCell<String> {
            private ContextMenu rootContextMenu;
    
            public MyTreeCell() {
                // instantiate the root context menu
                rootContextMenu = 
                    ContextMenuBuilder.create()
                        .items(
                                MenuItemBuilder.create()
                                    .text("Menu Item")
                                    .onAction(
                                        new EventHandler<ActionEvent>() {
                                            @Override
                                            public void handle(ActionEvent arg0) {
                                                System.out.println("Menu Item Clicked!");                                           
                                            }
                                        }
                                    )
                                    .build()
                            )
                        .build();
            }
    
            @Override
            public void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
    
                // if the item is not empty and is a root...
                if (!empty && getTreeItem().getParent() == null) {
                    setContextMenu(rootContextMenu);
                }
            }
        }
    }
    

    You can take a look at the TreeView tutorial to see other uses and examples related to this JavaFX control.