给树加上右键菜单,及实现菜单相应功能

15.4  给树加上右键菜单,及实现菜单相应功能

本节实例的效果如图15.5所示。给TreeViewer加右键菜单的方法和TableViewer相似,也要用到Action、ActionGroup、MenuManager类,当然程序要根据树的特点稍做改动。

图15.5  右键菜单效果图

(1)在15.3节主程序的tv.setInput(input)之后插入如下两句:

//--------------完整代码见文件:TreeViewer2.java--------------

MyActionGroup actionGroup = new MyActionGroup(tv);// 生成一个ActionGroup对象

actionGroup.fillContextMenu(new MenuManager());// 将按钮注入到菜单对象中

(2)创建MyActionGroup类,其代码如下所示。MyActionGroup内含各Action类,在实现Action时,对传入的结点对象要记得进行空值判断,因为TreeViewer的大部分方法都不支持空值参数,会导致异常并中断程序。

public class MyActionGroup extends ActionGroup {

         private TreeViewer tv;

         public MyActionGroup(TreeViewer treeViewer) {

                   this.tv = treeViewer;

         }

         // 生成菜单Menu,并将两个Action传入

         public void fillContextMenu(IMenuManager mgr) {

                   // 加入两个Action对象到菜单管理器

                   MenuManager menuManager = (MenuManager) mgr; // 类型转换

                   menuManager.add(new OpenAction());

                   menuManager.add(new RefreshAction());

                   menuManager.add(new ExpandAction());

                   menuManager.add(new CollapseAction());

                   menuManager.add(new AddEntryAction());

                   menuManager.add(new RemoveEntryAction());

                   menuManager.add(new ModifyEntryAction());

                   // 生成Menu并挂在树Tree上

                   Tree tree = tv.getTree();

                   Menu menu = menuManager.createContextMenu(tree);

                   tree.setMenu(menu);

         }

         // “打开”的Action类

         private class OpenAction extends Action {

                   public OpenAction() {

                            setText("打开");

                   }

                   public void run() {

                            ITreeEntry entry = getSelTreeEntry();

                            if (entry != null)

                                     MessageDialog.openInformation(null, null, entry.getName());

                   }

         }

         // 刷新的Action类

         private class RefreshAction extends Action {

                   public RefreshAction() {

                            setText("刷新");

                   }

                   // 如果在删除结点时,不同时从数据模型里删除结点。则执行本刷新后,该结点又会从

                   // 数据模型中取出并显示在界面上

                   public void run() {

                            tv.refresh();

                   }

         }

         // 展开当前结点的Action类

         private class ExpandAction extends Action {

                   public ExpandAction() {

                            setText("展开");

                   }

                   public void run() {

                            ITreeEntry entry = getSelTreeEntry();

                            if (entry != null)

                                     tv.expandToLevel(entry, 1); // 参数2是展开的层数

                   }

         }

         // 收缩当前结点的Action类

         private class CollapseAction extends Action {

                   public CollapseAction() {

                            setText("收缩");

                   }

                   public void run() {

                            ITreeEntry entry = getSelTreeEntry();

                            if (entry != null)

                                     tv.collapseToLevel(entry, -1); // 参数2是收缩的层数,-1指收缩所有子结点

                   }

         }

         // 给当前结点增加一个子结点的Action类

         private class AddEntryAction extends Action {

                   public AddEntryAction() {

                            setText("增加");

                   }

                   public void run() {

                            ITreeEntry entry = getSelTreeEntry();

                            if (entry == null || entry instanceof PeopleEntity)

                                     return;// 不能给“人”结点增加子结点

                            InputDialog dialog = new InputDialog(null, "增加子结点", "输入名称:", "a", null);

                            if (dialog.open() == InputDialog.OK) {// 如果单击OK按钮

                                     String entryName = dialog.getValue(); // 得到Dialog输入值

                                     // 根据单击结点的不同类型生成相应的子结点

                                     ITreeEntry newEntry = null;

                                     if (entry instanceof CountryEntity)

                                               newEntry = new CityEntity(entryName);

                                     else if (entry instanceof CityEntity)

                                               newEntry = new PeopleEntity(entryName);

                                     entry.getChildren().add(newEntry); // 新结点增加到数据模型中

                                     tv.add(entry, newEntry);// newEntry结点增加到entry之下,或用tv.refresh(entry,true)也行

                                     if (!tv.getExpandedState(entry)) // 如果entry是未展开结点则展开它

                                               tv.expandToLevel(entry, 1);

                            }

                   }

         }

         // 删除结点的Action类

         private class RemoveEntryAction extends Action {

                   public RemoveEntryAction() {

                            setText("删除");

                   }

                   public void run() {

                            ITreeEntry entry = getSelTreeEntry();

                            if (entry == null)

                                     return;

                            // 从数据模型里删除结点

                            List<ITreeEntry> list = (List<ITreeEntry>) tv.getInput();

                            remove(list, entry);

                            // 从界面删除结点,放在从模型删除之后,

                            //否则在删除某个结点的最后一个子结点时会出问题

                            tv.remove(entry);

                   }

                   private void remove(List<ITreeEntry> list, ITreeEntry entry) {

                            if (list == null)    return;

                            for (Iterator it = list.iterator(); it.hasNext();) {

                                     ITreeEntry o = (ITreeEntry) it.next();

                                     if (o.getName().equals(entry.getName())) {

                                               it.remove();

                                               return;

                                     } else {

                                               remove(o.getChildren(), entry);

                                     }

                            }

                   }

         }

         // 修改结点名称的Action类

         private class ModifyEntryAction extends Action {

                   public ModifyEntryAction() {

                            setText("修改");

                   }

                   public void run() {

                            ITreeEntry entry = getSelTreeEntry();

                            if (entry == null)         return;

                            InputDialog dialog = new InputDialog(null, "修改结点", "输入新名称", entry.getName(), null);

                            if (dialog.open() == InputDialog.OK) {

                                     String entryName = dialog.getValue();

                                     entry.setName(entryName);//修改数据模型

                                     tv.refresh(entry); // 刷新结点,等效于tv.update(entry,null);

                            }

                   }

         }

         // 为共用而自定义的方法:取得当前选择的结点

         private ITreeEntry getSelTreeEntry() {

                   IStructuredSelection selection = (IStructuredSelection) tv.getSelection();

                   return (ITreeEntry) (selection.getFirstElement());

         }

}

<!-- page -->

你可能感兴趣的:(右键菜单)