这两天我刚好也遇到这样的问题,今天想到一种办法解决了,具体的做法是这样的
首先,对不同类型的右键菜单用不同的ActionGroup来实现,比如,有PeopleActionGroup, CityActionGroup, CountryActionGroup, 在以上每个类中,编写不同的内部类extends Action类实现不同的菜单功能
其次,在TreeViewer类中,我没有找到合适的用来响应鼠标事件的监听器,(最初尝试使用)tv.addSelectionChangedListener( new ISelectionChangedListener(){
public void selectionChanged(SelectionChangedEvent event) {});
但是效果不是太好。最后会说明是为什么。
我们知道,TreeViewer类中组合了一个SWT Tree类,而且可以通过getTree()方法得到。而且在Tree类中鼠标的监听器类,所以就尝试用这种方法来实现
具体代码如下:
//代码片断
tree = tv.getTree();
tree.addMouseListener( new MouseAdapter(){
public void mouseDown(MouseEvent e) {
if( e.button == 3 ){
//鼠标单击右键,3D鼠标
// 检查是否点到了具体的节点
TreeItem treeItem = tree.getItem( new Point( e.x, e.y ) );
//没有点到具体结点
if( treeItem != null ){
//选中了某一节点
//selection和TreeItem是一致的,交回TreeViewer进行处理
IStructuredSelection selection =
( IStructuredSelection )tv.getSelection();
ITreeEntry entry = ( ITreeEntry )selection.getFirstElement();
//对不同类型的节点关联相应的右键菜单
if( entry instanceof CountryEntity){
System.out.println( "Inner policyActionGroup " + policyActionGroup );
policyActionGroup.fillContextMenu();
}else if( entry instanceof CityEntity ){
System.out.println( "ruleActionGroup " + ruleActionGroup );
ruleActionGroup.fillContextMenu();
}
}else{
//没有节点被选中
policyActionGroup.dispose();
ruleActionGroup.dispose();
}
}else if( e.button == 1 ){
//鼠标单击,左键,对应的代码
}
}
});
这里边的PolicyActionGroup, ruleAcitonGroup都是相应的AcitonGroup对应的实例
由于在SWT中菜单都是挂在某一Control上的,所以为了使程序运行过程中尽量的少生成对象,把陈刚ActionGroup例子中的程序改动如下
public class RuleActionGroup extends ActionGroup{
private TreeViewer tv;
private MenuManager menuManager;
public RuleActionGroup( TreeViewer tv ){
this.tv = tv;
}
/*
* 生成菜单Menu,并将Aciton传入
*/
public void fillContextMenu(){
/*
* 加入两个Action对象到菜单管理器
*/
//把menuManager声明成为成员变量,不用每次都添加Action?
if( menuManager == null ){
//第一次调用该方法时
menuManager = new MenuManager();
menuManager.add( new OpenAction() );
menuManager.add( new RefreshAction() );
menuManager.add( new AddEntryAction() );
menuManager.add( new RemoveEntryAction() );
}
/*
* 生成Menu并挂在Tree上
*/
Tree tree = tv.getTree();
Menu menu = menuManager.createContextMenu( tree );
//tree.setMenu( null );
tree.setMenu( menu );
}
/*
* 打开的Action类
*/
private class OpenAction extends Action{
public OpenAction(){
setText( "打开规则 " );
}
/*
* 继承自Action的方法,动作代码在此代码中
*/
public void run(){
}
}
/*
* 刷新的Action类
*/
private class RefreshAction extends Action{
public RefreshAction(){
setText( "刷新策略 " );
}
public void run(){
}
}
/*
* 增加的Action类
*/
private class AddEntryAction extends Action{
public AddEntryAction(){
setText( "添加额外逻辑 " );
}
public void run(){
}
}
}
/*
* 删除结点的Aciton类
*/
private class RemoveEntryAction extends Action{
public RemoveEntryAction(){
setText( "删除规则 " );
}
public void run(){
}
public void dispose() {
// TODO 自动生成方法存根
super.dispose();
tv.getTree().setMenu( null );
}
}
改动如下,没有复写AcitonGroup中的public void fillContextMenu( IMenuManager mgr )方法,而是自己实现了一个同名的方法。把MenuManager作为类的实例变量,只在第一次调用fillContextMenu()生成相应的menuManager,和Aciton对象,在dispose()方法中把书中挂的菜单清空,需要的时候再挂上。
http://topic.youkuaiyun.com/u/20070605/15/ba405d40-502e-40bd-b4d8-ba34b7e61eb9.html