eclipse 基于选定节点的 TreeViewer 上下文菜单 - SWT

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6207772/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 16:23:21  来源:igfitidea点击:

Context menu for TreeViewer based on selected node - SWT

javaeclipseeclipse-pluginswt

提问by AndaP

I need to create a context menu for a TreeViewer in an Eclipse plugin project. But, the menu should not contain constant items, they should vary depending on the type of the node that is selected. For example, my treeViewer has the following hierarchy:

我需要在 Eclipse 插件项目中为 TreeViewer 创建一个上下文菜单。但是,菜单不应包含固定项,它们应根据所选节点的类型而有所不同。例如,我的 treeViewer 具有以下层次结构:

Node A
 |
 --Node B
  |
   --Node C

For node A - I want to show a menu with an action, but for nodes B and C I don't want to show anything (no menu). I managed to create the menu for node A, but then I can't get rid of it when some other type of node is selected. My code looks like:

对于节点 A - 我想显示一个带有操作的菜单,但对于节点 B 和 CI 不想显示任何内容(无菜单)。I managed to create the menu for node A, but then I can't get rid of it when some other type of node is selected. 我的代码看起来像:

treeViewer.addSelectionChangedListener(
            new ISelectionChangedListener(){
                public void selectionChanged(SelectionChangedEvent event) {
                    if(event.getSelection() instanceof IStructuredSelection) {
                        IStructuredSelection selection = (IStructuredSelection)event.getSelection();            
                        Object o = selection.getFirstElement();     

                        MenuManager menuMgr = new MenuManager();

                        if (o instanceof NodeA){

                            Menu menu = menuMgr.createContextMenu(treeViewer.getControl());
                            treeViewer.getControl().setMenu(menu);
                            getSite().registerContextMenu(menuMgr, treeViewer);

                            menuMgr.add(new SomeAction());

                        }else {
                            //what ?
                        }
                    }

                }
            }   
    );

On the else branch I tried to call dispose(),removeAll()on the MenuManager...nothing works!

在else分支我试图调用dispose()removeAll()在MenuManager ...没有作品!

Any help is appreciated, thanks.

任何帮助表示赞赏,谢谢。

回答by Paul Webster

As @jeeeyul mentioned, you should only create one MenuManager to use within your view.

正如@jeeeyul 提到的,您应该只创建一个 MenuManager 以在您的视图中使用。

You can use New>Plug-in Project and the view template to get an example of a context menu in a view using a viewer, but basically in your createPartControl(Composite)method you would hook up your context manager.

您可以使用 New>Plug-in Project 和视图模板在使用查看器的视图中获取上下文菜单的示例,但基本上在您的createPartControl(Composite)方法中您将连接您的上下文管理器。

    MenuManager menuMgr = new MenuManager();
    menuMgr.setRemoveAllWhenShown(true);
    menuMgr.addMenuListener(new IMenuListener() {
        public void menuAboutToShow(IMenuManager manager) {
            SampleView.this.fillContextMenu(manager);
        }
    });
    Menu menu = menuMgr.createContextMenu(viewer.getControl());
    viewer.getControl().setMenu(menu);
    getSite().registerContextMenu(menuMgr, viewer);

Your fillContextMenu(MenuManager)method will have access to your viewer, so you can get the current selection from that. You can add whatever actions you want, even re-add actions after updating them with the current selection.

您的fillContextMenu(MenuManager)方法将可以访问您的查看器,因此您可以从中获取当前选择。您可以添加任何您想要的操作,甚至可以在使用当前选择更新操作后重新添加操作。

The registerContextMenu(*)call allows extension points like org.eclipse.ui.popupMenus and org.eclipse.ui.menus to contribute items to your context menu.

registerContextMenu(*)调用允许像 org.eclipse.ui.popupMenus 和 org.eclipse.ui.menus 这样的扩展点向上下文菜单提供项目。

回答by jeeeyul

Just use single Menu Manager. Do not make Menu Manager dynamically.

只需使用单个菜单管理器。不要动态创建菜单管理器。

in theory, It's possible you tried, but it's inefficient and it's not general way.

从理论上讲,您可能尝试过,但效率低下,而且不是通用方法。

Just make a Menu Manager and add all actions which you needs.

只需制作一个菜单管理器并添加您需要的所有操作。

when selection has been changed, call Action#setVisible(true|false)to hide or show menu items. You can also use Action#setEnable to enable/disable menu item.

when selection has been changed, call Action#setVisible(true|false)to hide or show menu items. 您还可以使用 Action#setEnable 启用/禁用菜单项。

ps. Menu Manager is not a menu GUI(likes TreeViewer is a not tree)

附:菜单管理器不是菜单 GUI(就像 TreeViewer 不是树一样)

It contributes Actions(business logic) to Menu(SWT). And It also manage visibility and enablement. We call this Contribution Manager. We can create a SWT menu very easy with this. (even we don't know about SWT, we just have to know only our business logic:Action) It's fundamental idea in JFace.

它将操作(业务逻辑)贡献给菜单(SWT)。它还管理可见性和启用。我们称之为贡献管理器。我们可以很容易地创建一个 SWT 菜单。(即使我们不知道 SWT,我们只需要知道我们的业务逻辑:Action)它是 JFace 中的基本思想。

When you add an action into manu manager, action will be wrapped with ActionContributionItem. It hooks action's state to update UI(visibility, enablement for menu, button, toolbar and so on). It also hooks UI to launch action when it pressed.

当您将一个动作添加到 manu 管理器时,动作将被 ActionContributionItem 包裹。它挂钩操作的状态以更新 UI(可见性、菜单、按钮、工具栏等的启用)。它还挂钩 UI 以在按下时启动操作。

If you are new to eclipse, It is easy to confuse role of SWT and JFace.

如果你是 eclipse 的新手,很容易混淆 SWT 和 JFace 的作用。

回答by Kasas

Thats the way I do it:

这就是我这样做的方式:

MenuManager menuMgr = new MenuManager();

        Menu menu = menuMgr.createContextMenu(viewer.getControl());
        menuMgr.addMenuListener(new IMenuListener() {
            @Override
            public void menuAboutToShow(IMenuManager manager) {
                // IWorkbench wb = PlatformUI.getWorkbench();
                // IWorkbenchWindow win = wb.getActiveWorkbenchWindow();
                if (viewer.getSelection().isEmpty()) {
                    return;
                }

                if (viewer.getSelection() instanceof IStructuredSelection) {
                    IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
                    Node object = (Node)selection.getFirstElement();

                    if (object.getModel() instanceof NodeA) {
                        manager.add(new Action();
                    } else if (object.getModel() instanceof NodeB) {

                        manager.add(new OtherAction());

                    }
                }
            }
        });
        menuMgr.setRemoveAllWhenShown(true);
        viewer.getControl().setMenu(menu);

I hope this helps ;)

我希望这有帮助 ;)

It is important to set removeAllWhenShownproperty of menu manager to false, in order to hide all the other nodes actions ;)

将菜单管理器的removeAllWhenShown属性设置为 false很重要,以便隐藏所有其他节点操作;)

回答by V Kash Singh

Suppose that you know how to create Action and you are only interested in context menu following example worked for me hope this bunch of code will help you

假设你知道如何创建 Action 并且你只对上下文菜单感兴趣,下面的例子对我有用希望这堆代码能帮助你

 private void hookContextMenu() {
    MenuManager contextMenu = new MenuManager();
    contextMenu.setRemoveAllWhenShown(true);
    contextMenu.addMenuListener(new IMenuListener() {

        @Override
        public void menuAboutToShow(IMenuManager manager) {



            IStructuredSelection sSelection = (IStructuredSelection) treeViewer.getSelection();

            }
            if(selectedObject instanceof A){
            manager.add(action);
            }

        }
    });