往eclipse的默认NavigationView中,添加右键菜单项是非常容易的,甚至不需要自己写代码,只要在plugin.xml中添加扩展项便可以了。
但是这远远达不到我们的要求。如果要我们在自己的rcp程序的View中添加右键弹出菜单就不是很容易了。现在我介绍一下如何在一个树视图中针对不同的TreeObject添加不同的右键弹出菜单的方法。
如果不清楚如何构建一个树,请参考
http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/CatalogSWT-JFace-Eclipse.htm, 这里有很多关于eclipse Tree的实例。简单将来,Eclipse中创建树有两种,一种是使用SWT提供的树,依照一定的格式给其提供数据,我自己只用这种方法创建一些简单的、静态的树。另一种方法,针对于RCP程序,可以使用JFace提供的TreeViewer类,非常灵活并且易于扩展。使用TreeViewer需要实现ITreeContentProvider接口和ITreeLableProvider接口。由于我的时间有限,不能向大家提供具体的实现方法,请原谅。可以参考以下文章:http://eclipse.org/articles/treeviewer-cg/TreeViewerArticle.htm
在大体了解了如何构造一个树之后,我们下面就来介绍右键弹出菜单context menu的实现方法。
一个TreeViewer 必须继承ViewPart方法,并且重写其中的createPartControl(Composite parent)类。


   public void createPartControl(Composite parent) {

   /* Set the imput data and image model of the tree viewer,
    * and layout the viewer on the left part of the composite.
    */
    viewer = new TreeViewer(parent);
    viewer.setContentProvider(new ViewContentProvider());
    viewer.setLabelProvider(new ViewLabelProvider());
    viewer.setInput(createDummyModel());
10
11   createActions();
12   createMenus();
13   createContextMenu(parent);
14
15   //handles the actions related with treeviewer.
16   makeActions(parent);
17 }
其中,第7到9行为设置TreeViewer的内容提供器、图像提供器、以及初始化时的输入数据。第13行为创建右键弹出菜单。

1     private void createContextMenu(Composite parent) {

3         MenuManager mgr = new MenuManager();
4         mgr.setRemoveAllWhenShown(true);
5         mgr.addMenuListener(new IMenuListener() {
6             public void menuAboutToShow(IMenuManager manager) {
7                fillContextMenu(manager);
8             }
9         });
10     Menu menu = mgr.createContextMenu(viewer.getControl());
11     viewer.getControl().setMenu(menu);
12     getSite().registerContextMenu(mgr, viewer);
13   }
第4行代码中,setRemoveAllWhenShown(true)的作用是清空以前显示的菜单项,当触发了menu事件时,重新填充(fillContextMenu),所以如果不把removeAllWhenShow置为true的话,每点一下右键你就会看到菜单项多出一倍来。Menu是swt的控件,而Menumanager是Jface中的控件,不象SWT那样直接同底层打交道。用MenuManager可以创建出一个Menu对象。第十行mgr.createContextMenu(viewer.getControl());这里的viewer即为上面的viewer。第十一行,然后我们将树的setMenu方法将树控件与Menu控件联系在一起就好了。
最重要的是第十二行,这是context menu能不能显示的关键。一个视图中可以有多个context menu, 而每一个context menu都必须注册给workbench。这需要通过调用
org.eclipse.ui.IWorkbenchPartSite.registerContextMenu(MenuManager menuManager, ISelectionProvider selectionProvider)或者(当有多个注册的context menu时)org.eclipse.ui.IWorkbenchPartSite.registerContextMenu(String menuId, MenuManager menuManager, ISelectionProvider selectionProvider) 增加的参数menuId用于区分不同的context menu。
接下来,我们有两种方法来创建右键弹出菜单项。第一种,实现fillContextMenu()方法。典型的实现代码如下:
1     protected void fillContextMenu(IMenuManager manager) {
2  
3         manager.add(openAction);
4         manager.add(removeAction);
5         manager.add(addAction);
6              } 

这些Action都可由自己定义创建。
另外的方法,可以编辑plugin.xml文件。不需要自己写任何代码便可以显示出自己想要的弹出项。
这次先讲到这里,下次介绍另外的一种实现方式。(主要是由于刚创建Blog,不知道如何插入图片,这么写太费劲也太枯燥了,相信大家一定不能忍了吧!咱们下次再见

Feedback

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-01-06 17:46 by 愿做鱼
亲爱的,我们还急着要看(二)

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-01-06 18:10 by nemo
对不起,最近实在太忙了,忙着做开题报告。
最早也要到两周后了。
有一些相关的例子你可以先看一下,虽是英语的,可还是很容易读懂。一直没写下去的一部分原因也是看到这篇文章,觉得不太有必要写了。
http://www.eclipse.org/articles/Article-action-contribution/Contributing%20Actions%20to%20the%20Eclipse%20Workbench.html

# 如何针对TreeViewer不同的TreeObject添加不同的右键弹出菜单  回复  更多评论   

2006-01-10 10:37 by 想不出问题的我
如何针对TreeViewer上不同的TreeObject添加不同的右键弹出菜单

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-01-10 13:30 by nemo
可以通过填写plugin.xml来进行操作。通过设置filter,典型格式如下:
<extension point="org.eclipse.ui.popupMenus">
<objectContribution id="org.eclipse.ui.articles.action.contribution.popup.object"
objectClass="org.eclipse.core.resources.IFile"
nameFilter="*.java">
<filter
name="projectNature"
value="org.eclipse.jdt.core.javanature">
</filter>
<action id="org.eclipse.ui.articles.action.contribution.object.action1"
label="Object Action 1"
icon="icons/red_dot.gif"
menubarPath="additions"
class="org.eclipse.ui.articles.action.contribution.ObjectAction1Delegate">
</action>
</objectContribution>
</extension>

此处objectClass设为你为你的TreeViewer设置的树对象类。nameFilter可以精确指定哪一个树对象(显示的名字)。
action标签设置你想要处理的事件操作,必须实现org.eclipse.ui.IObjectActionDelegate接口(让Eclipse自动完成),只要在其中实现run()方法,写出自己想要的操作即可。我印象中是这样的。
另外的方法你可以在createContextMenu中针对不同的TreeObject对象(通过viewer.getTree().getSelection()[0].getText()获知当前选择的树对象)构造不同的响应方法(用判断语句)。
关于第一种方法,上面给出的那个链接中有比较详细的说明,可以参考。
比较忙,有不明白的地方请包涵。也可以再提出来。有空时我会回复的。

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-02-28 14:13 by nemo
@想不出问题的我
可以设置nameFilter过滤树结点的名字。
比如对于文件结点而言,可根据文件的后缀名辨别不同的树结点,从而针对不同类型的文件设置不同的ContextMenu.

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-03-10 15:53 by 傲起
怎样在TreeViewer中显示根节点阿?

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-03-28 10:36 by sol
小弟最近也在学习RCP树是建立起来了但是在建立多层的时候遇到刷新不够及时的问题.困扰了我几天了.忘大虾指条路~








`

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-03-28 15:44 by nemo
我这里没有用别的方法,只调用viewer.refresh()方法。是不是监听机制出现了问题?

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-04-06 14:16 by nemo
@sol
这两天我又研究了一下关于刷新不及时的问题,有了一些答案。
建议不要使用refresh(void)方法。refresh(void)方法只有在大规模数据变动的情况下在使用,否则会延缓刷新。
viewer.refresh()会递归的更新所有树节点object,以及label和content,在这个过程中需要与树结构,标签提供器以及内容提供器紧密的交互,因而在出现较少数据变更时没有必要也不应该使用刷新方法。
还有另一个版本的刷新方法,可以用它来指定是否刷新现有元素的标签。建议使用刷新方法时不要使用viewer.refresh(),而使用viewer.refresh(boolean updateLabels)、viewer.refresh(Object element)、viewer.refresh(Object element,boolean updateLabels)
而update方法之刷新所选目标的label或是图像,而不管其子节点。如果该节点下新增加了一个子节点,调用update方法之后不会显示出来.
如果加载的数据过多,可新开一线程。

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-06-21 14:00 by 墓地守望者
我在系统托盘中加入弹出菜单,为什么不能显示
private void hookPopupMenu(final IWorkbenchWindow window) {
trayItem.addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
MenuManager trayMenu = new MenuManager();
Menu menu = trayMenu.createContextMenu(window.getShell());
actionBarAdvisor.fillTrayItem(trayMenu);
menu.setVisible(true);
}
});
}

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-06-25 20:24 by 一只不愿游泳的鱼
我也是一只不愿游泳的鱼,呵呵

# re: 往Eclipse RCP视图中添加右键弹出菜单(一)  回复  更多评论   

2006-07-15 02:20 by nemo
对不起大家啊,这段时间一直没有来得及管理博客。在忙毕设。现在可以歇一歇了。
如果要在上下文菜单里添加多极菜单的话,需要加入菜单分隔线,否则系统就会警告。
menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));

只有注册用户登录后才能发表评论。


网站导航:
 

posts - 21, comments - 74, trackbacks - 0, articles - 3

Copyright © nemo