• Eclipse中的TreeViewer类和ListViewer类


    TreeViewer和TableViewer在使用上还是有很多相似之处.TreeViewer中冶有TableViewer中的过滤器和排序器.具体使用看TableViewer中的使用.

    和Table有JFace的扩展TableViewer一样,Tree也有一个JFace中的扩展,那就是TreeViewer.因为TreeViewer和TableViewer继承自同一个父类StructuredViewer所以两者有很多方法的使用是一样的.例如:都使用setInput方法输入数据,都有内容器,标签器,以及排序器,过滤器等.

    建立一个树节点的接口类:

    树节点由两个基本特征,名称和子节点.这里把这两个特征抽象出来写成一个接口,然后将要做树节点的实体类实现此接口.

    主义这个接口不是必须的.仅仅是为了今后操作方便,以及规范化涉及才建立的.

    但是每个实体对应的都是树上的一个节点.这里定义一个树中节点的通用接口.

    然后每个实体类都实现这个接口.

    接着建立几个实体类:

    ITreeEntry.java

     1 /**
     2  * 树上的每个一个节点都对应的是一个实体,这个实体是树上的一个节点.
     3  * 首先在定义实体类(People City Country)之前要先定义这个接口ITreeEntry
     4  * 树的节点接口
     5  * @author kongxiaohan
     6  */
     7 public interface ITreeEntry {
     8     /*
     9      * 设置dedao 树节点的名称    
    10      * 只声明抽象方法,不声明字段名
    11      */
    12     public String getName();
    13     public void setName(String name);
    14     
    15     
    16     /*
    17      * 设置与得到子节点集合.
    18      */
    19     public void setChildren(List<ITreeEntry> children);
    20     public List<ITreeEntry> getChildren();
    21 }

    City.java

     1 /**
     2  * City城市实体类
     3  * @author kongxiaohan
     4  *
     5  */
     6 public class City implements ITreeEntry{
     7     private Long id; // 唯一识别码,在数据库里常为自动递增的ID列
     8     private String name;// 城市名
     9     
    10     private List<ITreeEntry> peoples;//City实体的子节点  城市中的人,装在一个List集合中
    11     
    12     public City(String name) {
    13         super();
    14         this.name = name;
    15     }
    16     
    17     public Long getId() {
    18         return id;
    19     }
    20     public void setId(Long id) {
    21         this.id = id;
    22     }
    23     public String getName() {
    24         return name;
    25     }
    26     public void setName(String name) {
    27         this.name = name;
    28     }
    29     
    30     //这个地方是设置子节点....当前是City实体,其子节点是People实体
    31     @Override
    32     public void setChildren(List<ITreeEntry> children) {
    33         //这个地方我犯了一错误,以前写习惯了,this.name = name
    34         //所以一开始这个地方我写的是this.peoples = peoples 
    35         //在Country实体类中也是这个错误,所以运行出来的程序只有一列国家名,国家下面的城市都没有了....
    36         this.peoples = children;
    37     }
    38 
    39     @Override
    40     public List<ITreeEntry> getChildren() {
    41         return peoples;
    42     }
    43 }

    Country.java

     1 /**
     2  * Country国家实体类
     3  * @author kongxiaohan
     4  */
     5 public class Country implements ITreeEntry {
     6     private Long id; // 唯一识别码,在数据库里常为自动递增的ID列
     7     private String name; // 国家名
     8     
     9     private List<ITreeEntry> cities; //Country实体的子节点是城市 City 此国家所包含的的城市的集合,集合元素为City对象
    10     
    11     public Country() {
    12     }
    13     
    14     public Country(String name) {
    15         super();
    16         this.name = name;
    17     }
    18     
    19     public Long getId() {
    20         return id;
    21     }
    22     public void setId(Long id) {
    23         this.id = id;
    24     }
    25     public String getName() {
    26         return name;
    27     }
    28     public void setName(String name) {
    29         this.name = name;
    30     }
    31     
    32     @Override
    33     public void setChildren(List<ITreeEntry> children) {
    34         this.cities = children;
    35     }
    36 
    37     @Override
    38     public List<ITreeEntry> getChildren() {
    39         return cities;
    40     }
    41 }

    People.java

     1 public class People implements ITreeEntry {
     2     private Long id; // 唯一识别码,在数据库里常为自动递增的ID列
     3     private String name; // 姓名
     4     private boolean sex; // 性别 true男,flase女
     5     private int age; // 年龄
     6     private Date createDate; // 记录的建立日期,是java.util.Date,而不是java.sql.Date
     7 
     8     public People(String name) {
     9         super();
    10         this.name = name;
    11     }
    12     public Long getId() {
    13         return id;
    14     }
    15     public void setId(Long id) {
    16         this.id = id;
    17     }
    18     public String getName() {
    19         return name;
    20     }
    21     public void setName(String name) {
    22         this.name = name;
    23     }
    24     public boolean isSex() {
    25         return sex;
    26     }
    27     public void setSex(boolean sex) {
    28         this.sex = sex;
    29     }
    30     public int getAge() {
    31         return age;
    32     }
    33     public void setAge(int age) {
    34         this.age = age;
    35     }
    36     public Date getCreateDate() {
    37         return createDate;
    38     }
    39     public void setCreateDate(Date createDate) {
    40         this.createDate = createDate;
    41     }
    42     
    43     
    44     //因为人是这个树的最小子节点,所以这个地方空实现接口中的这两个方法就可以了
    45     @Override
    46     public void setChildren(List<ITreeEntry> children) {
    47     }
    48     @Override
    49     public List<ITreeEntry> getChildren() {
    50         return null;
    51     }
    52 }

    制造各个实体类的工具类

    DataFactory.java

     1 /**
     2  * 此类负责生成TreeViewer的方法setInput所需要的参数.
     3  * @author kongxiaohan
     4  * 
     5  * 这个地方我没有用书中用的局部代码块,在组织代码的时候确实犯了一些小错误,
     6  * 确实体会到了局部代码块的意义,代码读起来容易,而且节省了内存.
     7  */
     8 public class DataFactory {
     9     /**
    10      * 在这个方法中定义生成的数据
    11      * 要有人People的数据对象
    12      * 要有国家Country的数据对象
    13      * 要有城市City的数据对象
    14      * @return
    15      */
    16     public static Object createTreeData(){
    17         //生成人People的数据对象
    18         People people1 = new People("张A");
    19         People people2 = new People("张B");
    20         People people3 = new People("张C");
    21         People people4 = new People("张D");
    22         People people5 = new People("张E");
    23         People people6 = new People("张F");
    24         People people7 = new People("张G");
    25         People people8 = new People("张H");
    26         People people9 = new People("张I");
    27         
    28         //生成城市City的数据对象
    29         City city1 = new City("北京");
    30         City city2 = new City("广州");
    31         City city3 = new City("东京");
    32         City city4 = new City("芝加哥");
    33         City city5 = new City("洛杉矶");
    34         
    35         //生成国家Country的的数据对象
    36         Country country1 = new Country("中国");
    37         Country country2 = new Country("日本");
    38         Country country3 = new Country("美国");
    39         
    40         /**
    41          * 将这些封装的对象建立关系.
    42          */
    43         //1.人和城市的关系 
    44         //张A 张B 张C 在帝都
    45         ArrayList<ITreeEntry> list1 = new ArrayList<ITreeEntry>();
    46         list1.add(people1);
    47         list1.add(people2);
    48         list1.add(people3);
    49         city1.setChildren(list1);
    50         
    51         //张D 张E 张F在广州 
    52         ArrayList<ITreeEntry> list2 = new ArrayList<ITreeEntry>();
    53         list2.add(people4);
    54         list2.add(people5);
    55         list2.add(people6);
    56         city2.setChildren(list2);        
    57         
    58         //张G 在东京
    59         ArrayList<ITreeEntry> list3 = new ArrayList<ITreeEntry>();
    60         list3.add(people7);
    61         city3.setChildren(list3);        
    62 
    63         //张I 在芝加哥
    64         ArrayList<ITreeEntry> list4 = new ArrayList<ITreeEntry>();
    65         list4.add(people8);
    66         city4.setChildren(list4);        
    67 
    68         //张H 在洛杉矶
    69         ArrayList<ITreeEntry> list5 = new ArrayList<ITreeEntry>();
    70         list5.add(people9);
    71         city5.setChildren(list5);        
    72         
    73         //2.城市和国家的关系
    74         //北京 上海  广州是中国的
    75         ArrayList<ITreeEntry> list6 = new ArrayList<ITreeEntry>();
    76         list6.add(city1);
    77         list6.add(city2);
    78         country1.setChildren(list6);
    79         
    80         //东京是日本的
    81         ArrayList<ITreeEntry> list7 = new ArrayList<ITreeEntry>();
    82         list7.add(city3);
    83         country2.setChildren(list7);
    84         
    85         //芝加哥和洛杉矶是美国的
    86         ArrayList<ITreeEntry> list8 = new ArrayList<ITreeEntry>();
    87         list8.add(city4);
    88         list8.add(city5);
    89         country3.setChildren(list8);
    90         
    91         //3.将国家置于一个对象之下,这个对象可以是一个List也可以是个数组
    92         //国家是这个树上的最上层的节点.国家和国家之间是并列的关系,把这几个国家放到一个List集合对象中.
    93         ArrayList<ITreeEntry> list9 = new ArrayList<ITreeEntry>();
    94         list9.add(country1);
    95         list9.add(country2);
    96         list9.add(country3);
    97         return list9;
    98     }
    99 }

    内容器:TreeViewerContentProvider.java

    标签器还比较简单,在TreeViewer中最主要和最复杂的是内容器,熟悉内容器是掌握TreeViewer的要点.

     1 /**
     2  * "内容器" 由它决定哪些对象记录应该输出在TreeViewer里显示.
     3  * @author kongxiaohan
     4  *
     5  */
     6 public class TreeViewerContentProvider  implements ITreeContentProvider{
     7 
     8     /**
     9      * 这个方法决定树的一级目录显示哪些对象
    10      * @param inputElement 是用tv.setInput()方法输入的那个对象
    11      * @return Object[]一个数组,数组中一个元素就是一个结点
    12      */
    13     @Override
    14     public Object[] getElements(Object inputElement) {
    15         if (inputElement instanceof List) {
    16             List list = (List) inputElement;
    17             return list.toArray();
    18         } else {
    19             return new Object[0]; // 生成一个空数组
    20         }
    21     }
    22     
    23     
    24     /**
    25      * 判断某结点是否有子结点。如果有子结点,这时结点前都有一个“+”号图标
    26      * 
    27      * @param element 需要判断是否有子的结点
    28      * @return true有子结点,false无子结点
    29      */
    30     @Override
    31     public boolean hasChildren(Object element) {
    32         ITreeEntry entry = (ITreeEntry) element;
    33         List<ITreeEntry> list = entry.getChildren();
    34         if (list == null || list.isEmpty()) {
    35             return false;
    36         } else {
    37             return true;
    38         }
    39     }
    40     
    41     
    42     /**
    43      * 由这个方法决定父结点应该显示那些子结点。
    44      * 
    45      * @param parentElement 当前被点击的结点对象
    46      * @return 由子结点做为元素的数组
    47      */
    48     @Override
    49     public Object[] getChildren(Object parentElement) {
    50         ITreeEntry entry = (ITreeEntry) parentElement;
    51         List<ITreeEntry> list = entry.getChildren();
    52         if (list == null || list.isEmpty()) {
    53             return new Object[0];
    54         } else {
    55             return list.toArray();
    56         }
    57     }
    58 
    59     //>>>>>>>>>>>>>>>>>>>>>>>>>书上说以下三个方法是没有用的,空实现就哦了>>>>>>>>>>>>>>>>>>>>>>
    60     @Override
    61     public Object getParent(Object element) {
    62         return null;
    63     }
    64 
    65     @Override
    66     public void dispose() {
    67     }
    68     
    69     @Override
    70     public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
    71     }
    72 }

    程序说明:在内容器中最关键的是getElements,hasChildren,getChildren这三个方法.

    1.getElements自在显示"第一级"结点的时候才会被执行.

    2.hasChildren主要用于判断当前说系那是的节点是否有子节点,如果有子节点则前面显示一个"+"号图标,而有"+"号的结点则可以单击展开其下一级的子节点.

    3.当单击右"子"的结点的时候,才会执行getChildren方法.展开其子节点后,又会对子节点执行一遍hasChildren方法,以决定其各子结点前是否显示"+"图标.

    下面是"内容器"在启动,单击,关闭窗口时执行的过程.

    下面以本例来解释这个图:

    1.树界面启动的时候 ,先执行inputChanged()方法,接着执行getElements方法,其inputElement参数就是由setInput传入的对象:包含所有实体对象的List,此List在getElements中被转化成一个数组,数组包含第一级结点的两个元素,中国,美国,日本,他们将首先显示在页面上.接下来执行三次hasChildren方法,判断中国,日本和美国是否有子节点.他们都有子节点.,所以方法返回True,两结点前都显示"+"图标.

    2.单击右子节点的中国:先执行一次getChildren方法,方法的parentElement参数就是中国结点对象.方法中把中国的子节点取出转换陈给一个数组返回,此数组包含3个元素"北京,上海,济南".接下来连续执行3次hasChildren方法来判断"北京,上海,济南"是否有子节点,如果有在结点的前面显示一个"+"图标.

    3.单击没有子节点的结点:不会有执行内容器中的任何方法.

    4.关闭窗口:会先后执行inputChanged和dispose方法.

    标签器TreeViewerLableProvider.java

    将标签器写成单独的外部类,以便于后面的实例共用,其代码如下,在getText方法中element的类型可以是国家,城市,人,由于他们都是属于一个接口,所以getText的代码简洁不少.getImage()的实现参考TableViewer的标签器.

     1 /**
     2  * "标签器" 控制记录在树中显示的文字和图像等.
     3  * @author kongxiaohan
     4  */
     5 public class TreeViewerLableProvider implements ILabelProvider {
     6 
     7     /**
     8      * 记录显示的文字。不能返回NULL值
     9      */
    10     @Override
    11     public String getText(Object element) {
    12         //得到这个节点对应的名字,首先对element进行强制类型转换
    13         ITreeEntry entry = (ITreeEntry) element;
    14         return entry.getName();
    15     }
    16     
    17     /**
    18      * 记录显示的图像,可以返回NULL值
    19      */    
    20     @Override
    21     public Image getImage(Object element) {
    22         return null;
    23     }
    24     
    25 //>>>>>>>>>>>>>>>>>>>>>>书上说一下几个方法没有用,空实现就可以了.>>>>>>>>>>>>>>>>>>>>>>>>>    
    26     @Override
    27     public void addListener(ILabelProviderListener listener) {
    28         // TODO Auto-generated method stub
    29         
    30     }
    31 
    32     @Override
    33     public void removeListener(ILabelProviderListener listener) {
    34         // TODO Auto-generated method stub
    35         
    36     }
    37     @Override
    38     public void dispose() {
    39         // TODO Auto-generated method stub
    40         
    41     }
    42     @Override
    43     public boolean isLabelProperty(Object element, String property) {
    44         // TODO Auto-generated method stub
    45         return false;
    46     }
    47 }

    给TreeViewer加上右键菜单的方法和TableViewer相似,也要用到Action,ActionGroup,MenuManager类.当然程序要根据树的特点稍作改动.

    MyActionGroup内含有各Action类,在实现Action时,对传入的结点对象要记得进行空值判断.因为TreeViewer的大部分方法都不支持空值参数.会导致异常并中断程序.

    MyActionGroup.java

      1 public class MyActionGroup extends ActionGroup {
      2     //ActionGroup这是个抽象类,但是其中并没有抽象方法.
      3     private TreeViewer treeViewer;
      4 
      5     //构造方法
      6     public MyActionGroup(TreeViewer treeViewer) {
      7         this.treeViewer = treeViewer;
      8     }
      9     
     10     /**
     11      * 生成菜单Menu,并将两个Action传入
     12      */
     13     public void fillContextMenu(IMenuManager mgr) {
     14         /*
     15          * 加入两个Action对象到菜单管理器
     16          */
     17         MenuManager menuManager = (MenuManager) mgr; // 把接口类转换成其实现类.
     18         //用MenuManager管理Action
     19         menuManager.add(new OpenAction());
     20         menuManager.add(new RefreshAction());
     21         menuManager.add(new ExpandAction());
     22         menuManager.add(new CollapseAction());
     23         menuManager.add(new AddEntryAction());
     24         menuManager.add(new RemoveEntryAction());
     25         menuManager.add(new ModifyEntryAction());
     26         /*
     27          * 把这些功能加入到右键的Menu菜单中.
     28          */
     29         Tree tree = treeViewer.getTree();
     30         Menu menu = menuManager.createContextMenu(tree);
     31         tree.setMenu(menu);
     32     }
     33     
     34     /**
     35      * 打开"菜单"对应的Action类
     36      */
     37     private class OpenAction extends Action {
     38         public OpenAction() {
     39             setText("打开");
     40         }
     41         /**
     42          * 继承自Action的方法,动作代码写此方法中
     43          */
     44         //覆盖Action中的run()方法.
     45         public void run() {
     46             ITreeEntry obj = getSelTreeEntry();//getgetSelTreeEntry()得到当前节点
     47             if (obj != null) {
     48                 //弹出一个这个节点名字的对话框.
     49                 MessageDialog.openInformation(null, null, obj.getName());
     50             }
     51         }
     52     }
     53     
     54     /**
     55      * 刷新对应的Action类.
     56      */
     57     private class RefreshAction extends Action {
     58         public RefreshAction() {
     59             setText("刷新");
     60         }
     61 
     62         //覆盖Action类中的run()方法,里面是调用的refresh()方法.
     63         public void run() {
     64             treeViewer.refresh();// 调用TreeViewer的刷新方法
     65         }
     66     }
     67 
     68     /**
     69      * 展开当前结点的Action类
     70      */
     71     private class ExpandAction extends Action {
     72         public ExpandAction() {
     73             setText("展开");
     74         }
     75         //重写run()方法
     76         public void run() {
     77             ITreeEntry obj = getSelTreeEntry();
     78             if (obj != null) {
     79                 treeViewer.expandToLevel(obj, 1); 
     80                 // 这个方法后面的数字是展开的层级数.这个地方设置成仅仅展开1个层级.
     81             }
     82         }
     83     }
     84 
     85     /**
     86      * 收缩当前结点的Action类
     87      */
     88     private class CollapseAction extends Action {
     89         public CollapseAction() {
     90             setText("收缩");
     91         }
     92         //重写run()方法
     93         public void run() {
     94             ITreeEntry obj = getSelTreeEntry();
     95             if (obj != null) {
     96                 treeViewer.collapseToLevel(obj, -1); // -1为将当前结点的所有子结点收缩
     97             }
     98         }
     99     }
    100 
    101     /**
    102      * 给当前结点增加一个子结点的Action类
    103      */
    104     private class AddEntryAction extends Action {
    105         public AddEntryAction() {
    106             setText("增加");
    107         }
    108         @Override
    109         public void run() {
    110             ITreeEntry obj = getSelTreeEntry();
    111             if (obj == null || obj instanceof People) {
    112                 return;
    113             }
    114             InputDialog dialog = new InputDialog(null, "给当前结点增加一个子结点", "输入名称", "请输入你要增加的节点的名字", null);
    115             if (dialog.open() == InputDialog.OK) {// 如果单击OK按钮
    116                 String entryName = dialog.getValue(); // 得到Dialog输入值
    117                 /* 根据单击结点的不同类型生成相应的子结点 */
    118                 ITreeEntry newEntry = null;
    119                 if (obj instanceof Country) {
    120                     newEntry = new City(entryName);
    121                 } else if (obj instanceof City) {
    122                     newEntry = new People(entryName);
    123                 }
    124                 /* 在增加子结点之前将父结点展开 */
    125                 if (!treeViewer.getExpandedState(obj)) {
    126                     treeViewer.expandToLevel(obj, 1);
    127                 }
    128                 treeViewer.add(obj, newEntry);// 增加结点
    129             }
    130         }
    131     }
    132 
    133     /**
    134      * 删除结点的Action类
    135      */
    136     private class RemoveEntryAction extends Action {
    137         public RemoveEntryAction() {
    138             setText("删除");
    139         }
    140         @Override
    141         public void run() {
    142             ITreeEntry obj = getSelTreeEntry();
    143             if (obj == null) {
    144                 return;
    145             }
    146             treeViewer.remove(obj);
    147         }
    148     }
    149 
    150     /**
    151      * 修改结点名称的Action类
    152      */
    153     private class ModifyEntryAction extends Action {
    154         public ModifyEntryAction() {
    155             setText("修改");
    156         }
    157         @Override
    158         public void run() {
    159             ITreeEntry obj = getSelTreeEntry();
    160             if (obj == null) {
    161                 return;
    162             }
    163             InputDialog dialog = new InputDialog(null, "修改结点", "输入新名称", obj.getName(), null);
    164             if (dialog.open() == InputDialog.OK) {
    165                 String entryName = dialog.getValue();//得到对话框中的值.
    166                 obj.setName(entryName);//给这个节点设置成得到的对话框中的名字.
    167                 treeViewer.refresh(obj); // 刷新结点
    168             }
    169         }
    170     }
    171     /**
    172      * 这个方法是自定义的方法,这个方法的作用就是得到当前选择的节点.
    173      */
    174     private ITreeEntry getSelTreeEntry() {
    175         IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
    176         ITreeEntry treeEntry = (ITreeEntry) (selection.getFirstElement());
    177         return treeEntry;
    178     }
    179 }

    TreeViewer.java的实例

     1 public class TreeViewer1 {
     2     public static void main(String[] args) {
     3         TreeViewer1 window = new TreeViewer1();
     4         window.open();
     5     }
     6     
     7     //定义这个open()方法.就是创建一个典型的SWT程序的步骤
     8     public void open(){
     9         //1.Display负责管理一实现循环和控制UI线程和其他线程之间的通信
    10         final Display display = new Display();
    11         //2.创建一个或者多个Shell(shell是程序的主窗口)
    12         final Shell shell = new Shell();
    13         //3.设置shell的布局.
    14         shell.setSize(200, 300);
    15         //设置shell的布局为FillLayout
    16         shell.setLayout(new FillLayout());
    17         shell.setText("TreeViewer的第一个例子");
    18         
    19         
    20         Composite c = new Composite(shell, SWT.NONE);
    21         c.setLayout(new FillLayout());
    22         TreeViewer treeViewer = new TreeViewer(c, SWT.BORDER);
    23         treeViewer.setContentProvider(new TreeViewerContentProvider());
    24         treeViewer.setLabelProvider(new TreeViewerLableProvider());
    25         // 和TableViewer一样,数据的入口也是setInput方法
    26         Object inputObj = DataFactory.createTreeData();
    27         treeViewer.setInput(inputObj);
    28         
    29         /*
    30         //调用自定义的方法创建表格
    31         createTableViewer(shell);
    32         //4.设定内容器
    33         tableviewer.setContentProvider(new TableViewerContentProvider());
    34         //5.设定标签器
    35         tableviewer.setLabelProvider(new TableViewerLabelProvider());
    36         //6.用setInput输入数据(把PeopleFactory产生的List集合传进来)
    37         tableviewer.setInput(PeopleFactory.getPeoples());
    38         */
    39         
    40         //7.创建Shell中的组件(这个例子中没有加入组件,只有一个空窗口)
    41         shell.open();
    42         //8.写一个时间转发循环
    43         while(!shell.isDisposed()){//如果主窗口没有关闭,则一直循环
    44             //dispose 是"处理,处置,毁掉"的意思
    45             if(!display.readAndDispatch()){//// 如果display不忙
    46                 display.sleep();// display休眠
    47             }
    48         }
    49     }
    50 }

    TreeViewer1.java的运行结果图

    TreeViewer2.java

     1 public class TreeViewer2 {
     2 
     3     public static void main(String[] args) {
     4         TreeViewer2 window = new TreeViewer2();
     5         window.open();
     6     }
     7     
     8     public void open() {
     9         final Display display = new Display();
    10         final Shell shell = new Shell();
    11         shell.setSize(200, 300);
    12 
    13         shell.setLayout(new FillLayout());
    14         Composite c = new Composite(shell, SWT.NONE);
    15         c.setLayout(new FillLayout());
    16         TreeViewer treeViewer = new TreeViewer(c, SWT.BORDER);
    17         treeViewer.setContentProvider(new TreeViewerContentProvider());
    18         treeViewer.setLabelProvider(new TreeViewerLableProvider());
    19         Object inputObj = DataFactory.createTreeData();
    20         //>>>>>>>>>>>>>相比于TreeViewer1.java增加的>>>>>>>>>>>>>>>>>>>>>>>>>
    21         //生成一个ActionGroup对象
    22         MyActionGroup actionGroup = new MyActionGroup(treeViewer);
    23         // 调用fillContextMenu方法将按钮注入到菜单对象中
    24         actionGroup.fillContextMenu(new MenuManager());
    25         // --------------加入代码:END--------------------
    26         treeViewer.setInput(inputObj);
    27         // -----------------------------
    28         shell.open();
    29         while (!shell.isDisposed()) {
    30             if (!display.readAndDispatch()) {
    31                 display.sleep();
    32             }
    33         }
    34     }
    35 }

    TreeViewer2.java的运行结果图:

     上面的这个是<<Eclispe从入门到精通>>中第一版的代码,在第二版中对一些功能进行了一些改进.

    该进在于"不同的结点显示不同的菜单".

    树的"人"结点是没有子节点的.因此对于"人"这个节点来说,右键菜单中的"展开,收缩,增加"菜单项都没有任何意义,应该隐藏起来,再根据当前节点的类型决定要将哪些Action加入菜单中.按着这个思路将MyActionGroup类的fillContextMenu方法修改如下:

  • 相关阅读:
    前言
    实用逆袭课【时间管理、记忆训练、工作效率、人际社交】
    读书确实是一辈子的事
    求职宝典(笔记不详细,但你自己看完消化了真的受用)
    重新认识【时间、金钱、自我、人际关系】
    即兴演讲不是即兴
    大数据和AI的未来畅想
    女性30的思考1
    第四课 人际关系
    第三课 干好工作
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/4178096.html
Copyright © 2020-2023  润新知