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

Java 基于选定节点的TreeViewer上下文菜单-SWT,java,eclipse,eclipse-plugin,swt,Java,Eclipse,Eclipse Plugin,Swt,我需要在Eclipse插件项目中为TreeViewer创建上下文菜单。但是,菜单不应包含常量项,它们应根据所选节点的类型而有所不同。例如,我的treeViewer具有以下层次结构: Node A | --Node B | --Node C 对于节点A-我想显示带有操作的菜单,但是对于节点B和节点C,我不想显示任何内容(无菜单)。 我设法为节点A创建了菜单,但是当选择了其他类型的节点时,我无法摆脱它。我的代码如下所示: treeViewer.addSelectionChangedL

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

Node A
 |
 --Node B
  |
   --Node C
对于节点A-我想显示带有操作的菜单,但是对于节点B和节点C,我不想显示任何内容(无菜单)。 我设法为节点A创建了菜单,但是当选择了其他类型的节点时,我无法摆脱它。我的代码如下所示:

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 ?
                        }
                    }

                }
            }   
    );
在else分支上,我试图调用MenuManager上的
dispose()
removeAll()
,但没有任何效果


感谢您的帮助。

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

从理论上讲,你可能尝试过,但它效率低下,而且不是一般的方法

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

更改选择后,调用Action#setVisible(true | false)隐藏或显示菜单项。 您还可以使用Action#setEnable启用/禁用菜单项

附言。 菜单管理器不是菜单GUI(就像TreeViewer不是树)

它为菜单(SWT)提供操作(业务逻辑)。它还可以管理可见性和启用。我们称之为捐款经理。我们可以很容易地创建SWT菜单。(即使我们不知道SWT,我们也只需要知道我们的业务逻辑:操作)这是JFace的基本理念

在manu manager中添加操作时,操作将被ActionContributionItem包装。它将操作的状态挂接到更新UI(可见性、菜单、按钮、工具栏等的启用)。它还钩住UI,以便在按下时启动操作


如果您是eclipse新手,很容易混淆SWT和JFace的角色。

正如@jeeeyul所提到的,您应该只创建一个菜单管理器在视图中使用

您可以使用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);
您的
fillContextMenu(菜单管理器)
方法将访问您的查看器,因此您可以从中获取当前选择。您可以添加任何需要的操作,甚至在使用当前选择更新操作后重新添加操作

registerContextMenu(*)
调用允许诸如org.eclipse.ui.popupMenus和org.eclipse.ui.menu之类的扩展点将项目添加到上下文菜单中。

我就是这样做的:

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);
我希望这有帮助;)


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

假设您知道如何创建操作,并且只对上下文菜单感兴趣,下面的示例对我有用,希望这组代码能对您有所帮助

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

        }
    });

谢谢你的提示,现在我只创建一次菜单,如果有选择,我会调用action.setEnabled(false)。这工作正常,但我没有找到一个setVisible方法来执行操作。我希望在选择其他节点时将其隐藏,而不是将其灰显。感谢如果您添加包含您的操作的
ActionContributionItems
,则它们有一个
setVisible(boolean)
方法。但是您应该选择
setRemoveAllWhenShown(*)
或更新
ActionContributionItems
的可见性,因为它们是不同的方法。是的,我现在正在使用这种方法。在我的其他视图中,我只这样创建过一次。但我真正关心的是如何更改菜单的内容。fillContextMenu(*)在每个菜单SWT.Show事件上都被调用。您可以使用该方法每次更改菜单的内容。