TreeViewer如何在不同类型的节点上显示不同的右键菜单?

这两天我刚好也遇到这样的问题,今天想到一种办法解决了,具体的做法是这样的 

首先,对不同类型的右键菜单用不同的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.csdn.net/u/20070605/15/ba405d40-502e-40bd-b4d8-ba34b7e61eb9.html

你可能感兴趣的:(.net)