right click menu option in the tree root node

2019-07-14 19:09发布

问题:

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")
);

回答1:

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.