【问题标题】:Context menu for TreeViewer based on selected node - SWT基于所选节点的 TreeViewer 上下文菜单 - SWT
【发布时间】:2011-09-06 15:47:25
【问题描述】:

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

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

对于节点 A - 我想显示一个带有操作的菜单,但对于节点 B 和 C,我不想显示任何内容(无菜单)。 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 ?
                        }
                    }

                }
            }   
    );

在 else 分支上,我尝试在 MenuManager 上调用 dispose(),removeAll()...没有任何效果!

感谢任何帮助,谢谢。

【问题讨论】:

    标签: java eclipse eclipse-plugin swt


    【解决方案1】:

    只需使用单个菜单管理器。 不要动态制作菜单管理器。

    理论上,你有可能尝试过,但效率低下,也不是一般的方法。

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

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

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

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

    当你在manu manager中添加一个action时,action会被ActionContributionItem包裹起来。它挂钩动作的状态以更新 UI(可见性、菜单、按钮、工具栏等的启用)。它还挂钩 UI 以在按下时启动操作。

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

    【讨论】:

    • 感谢您的提示,现在我只创建一次菜单,然后在进行选择时调用 action.setEnabled(false)。这工作正常,但我没有找到用于 Action 的 setVisible 方法。我想在选择其他节点时将其隐藏,而不是使其变灰。谢谢
    • 如果您添加包含您的操作的ActionContributionItems,它们有一个setVisible(boolean) 方法。但是您应该选择setRemoveAllWhenShown(*) 或更新ActionContributionItems 的可见性,因为它们是不同的方法。
    【解决方案2】:

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

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

    registerContextMenu(*) 调用允许 org.eclipse.ui.popupMenus 和 org.eclipse.ui.menus 等扩展点向上下文菜单添加项目。

    【讨论】:

    • 是的,我现在正在使用这种方法。在我的其他观点中,我只创建了一次这样的。但我真正关心的是如何更改菜单的内容。
    • fillContextMenu(*) 在每个菜单 SWT.Show 事件上调用。您可以在该方法中每次更改菜单的内容。
    【解决方案3】:

    我就是这样做的:

    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 很重要,以便隐藏所有其他节点的操作;)

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-12
        • 1970-01-01
        • 2014-10-30
        • 2019-08-02
        • 2013-02-17
        • 1970-01-01
        • 2010-09-05
        • 1970-01-01
        相关资源
        最近更新 更多