基于所选节点的 TreeViewer 上下文菜单 - SWT
Posted
技术标签:
【中文标题】基于所选节点的 TreeViewer 上下文菜单 - SWT【英文标题】:Context menu for TreeViewer based on selected node - 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()
...没有任何效果!
感谢任何帮助,谢谢。
【问题讨论】:
【参考方案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);
);
【讨论】:
以上是关于基于所选节点的 TreeViewer 上下文菜单 - SWT的主要内容,如果未能解决你的问题,请参考以下文章