目标: |
1. 掌握JTree应用,树节点的操作; 2. 使用JTree展数,管理对象。 |
1.JTree的创建: 2
2.用JTree展示学生日志系统界面: 4
3.JTree节点的选中和信息获取 9
4.JTree的编辑《日志管理实现》: 13
5.完善分析 20
总结和任务: 23
在以上的示例中,我们都是创建默认的Javax.swing.JTree组件,本节就要示例,如何根据我们的需要创建自定义结构的JTree组件。首要明白的概念间:JTree上的节点分为两种,即枝节点和叶节点,其下有叶节点的,就称做枝节点,或称叶节点的父节点。
不论是叶节点,还是枝节点,在代码中,都是表现为一个javax.swing.tree.DefaultMutableTreeNode类的对象,DefaultMutableTreeNode有一个方法,可以将其它的DefaultMutableTreeNode对象加为自己的子节点;还有一个setUserObject(Object obj)和getUserObject方法,用来设定(或取得)节点内保存的对象。
请看如下代码,创建一个简单的树:
//JTree应用示例 public class TestJTree extends javax.swing.JFrame { //程序入口 public static void main(String[] args) { TestJTree tj=new TestJTree(); tj.init(); }
//初始化界面内容 public void init() { this.setTitle("东方标准JTree示例"); this.setSize(300, 400); java.awt.FlowLayout fl = new java.awt.FlowLayout(); this.setLayout(fl); // 将自己创建的树加到界面上: javax.swing.JTree tree = createTree(); this.add(tree); this.setDefaultCloseOperation(3); this.setVisible(true); } //创建一个自定义树 public javax.swing.JTree createTree() { // 创建默认树 javax.swing.JTree tree = new javax.swing.JTree(); // 首先,创建一个根节点: javax.swing.tree.DefaultMutableTreeNode rootNode = new javax.swing.tree.DefaultMutableTreeNode(); // 设定节点上的数据对象,节点显示标题则为设定对象的toString()值 rootNode.setUserObject("树的测试"); // 树下有5个组: for (int i = 0; i < 5; i++) { DefaultMutableTreeNode teamNode = new DefaultMutableTreeNode(); teamNode.setUserObject("第" + i + "组"); // 将组节点加到根节点上: rootNode.add(teamNode); for (int t = 0; t < 6; t++) { DefaultMutableTreeNode userNode = new DefaultMutableTreeNode(); userNode.setUserObject("第" + t + "个用户"); // 将用户节点加到组节点上: teamNode.add(userNode); } // 创建树的Model对象,创建时传入根节点: javax.swing.tree.DefaultTreeModel dm = new DefaultTreeModel( rootNode); // 将模型设给树,树上显示的将上前面所加载的节点 tree.setModel(dm); // 设定树上的图标 // ImageIcon leafIcon = new ImageIcon("src/budy_init.gif"); // DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); // renderer.setLeafIcon(leafIcon); // tree.setCellRenderer(renderer); } return tree; } } |
JTree创建时,关键的步骤就是:
1. 创建DefaultMutableTreeNode对象,设用其setUserObject设置节点的数据对象,这个节点的标签将显示为所设定(传入)的对象的toString方法返回值;
2. 给DefaultMutableTreeNode对象添加做为子节点的DefaultMutableTreeNode对象;
3. 将第一个,即要做为根节点的DefaultMutableTreeNode对象用来构造一个javax.swing.tree.DefaultTreeModel对象。
4. 将新建的DefaultTreeModel对象set给JTree对象即可。
比较简单吧,跟JMenu的应用方式差不了多少,就是一个一个的向上加。
JTree通常用来展示目录结构型的数据,例如学生管理系统中的分组和每组的学生数据;现在,假设我们要编写一个学生的日志管理系统,将界面用JTree展示:
假设我们要做一个学生日志管理系统:即每个学生每天都要写一篇学习日志,通过我们的程序保存和查看:
1.系统中就必须存在学生对象和每个学生的日志对象;我们首先要编写一个学生类和日志类。
2.系统中一个学生对象可能会有多个日志对象;
3.每个日志对象肯定属于某一个学生对象。
4.通过一个JTree组件展示,JTree上的每个一级节点为一个学生对象,点击后,展示出下面的子节点为用户的日志对象。
经过简单的分析:
学生类必须有的属性:id,name,age
日志类必须有的属性:所属学生的id,title,content,createTime
学生类代码如下:
import java.util.ArrayList; import java.util.List; //学生类定义 public class UserInfo { private int id; private String name; private int age; // 一个学生对象,有属于自己的多个日志对象,在其内部用队列存放 private List<UserBlog> blogList = new ArrayList(); // 为某个学生的日志队列中加入一个日志对象 public void addBlog(UserBlog blog) { blogList.add(blog); } // 取得学生的所有日志对象 public List<UserBlog> getBlogList() { return this.blogList; } // 对应的get/set各属性的方法: public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } |
日志类定义的代码如下(随后的代码中,将省略属性对应的get/set方法):
//日志类定义 public class UserBlog { private int id; private int id_userInfo;// 日志所属学生对象的学生ID private String title; private String content; private String createTime;// 日志创建时间 yyyymmddhh格式 // 一篇日志所属的学生对象 private UserInfo userinfo; // 以下为对应属性的get/set方法. . . |
以上代码需要特别注意的是:学生类在定义时,要考虑到每个学生对象与其日志对象的对应关系,这种关系,可以在设计类时定义好,后面使用时就非常方便:
学生对象与日志对象之间的关系,可以描述为:
1.一个学生对象,有多个日志对象,这是一对多的关系;在学生类定义时,代码体现为:
. . . // 一个学生对象,有属于自己的多个日志对象,在其内部用队列存放 private List<UserBlog> blogList = new ArrayList(); // 为某个学生的日志队列中加入一个日志对象 public void addBlog(UserBlog blog) { blogList.add(blog); } // 取得学生的所有日志对象 public List<UserBlog> getBlogList() { return this.blogList; } . . . |
对于使用UserInfo对象的其它对象而言,只要调用UserInfo对象的getBlogList即可得到这个对象的所有日志对象。
2.每个日志对象,都有自己所属的一个学生对象,这是多对一的关系;UserBlog类中体现为:
. . . private int id_userInfo;// 日志所属学生对象的学生ID private UserInfo userinfo; // 一篇日志所属的学生对象 //得到或设定日志对象所属的UserInfo对象 public UserInfo getUserinfo() { return userinfo; } public void setUserinfo(UserInfo userinfo) { this.userinfo = userinfo; } public int getId_userInfo() { return id_userInfo; } public void setId_userInfo(int id_userInfo) { this.id_userInfo = id_userInfo; } |
在UserBlog类中定义了它所属的UserInfo对象为属性,同时,又定义了它所属的UserInfo对象的id,这看起来是重复了,但这样,会方便后面某些使用这些对象的场景。一般情况下,只要定义一个就行了。
接下来就很简单,我们用程序模拟生成UserInfo和 UserBlog对象,并将其显示到JTree上,首先编写模拟成生用户数据对象的类:
import java.util.ArrayList; import java.util.List; //负责生成模拟数据的类 public class UserDao { //生成模拟的用户对象列表: public List<UserInfo> getAllUser(){ //保存生成的用户对象的列表: List<UserInfo> userList=new ArrayList(); for(int i=0;i<5;i++){//生成5个UserInfo对象 UserInfo us=new UserInfo(); us.setId(i); us.setAge(20+i); us.setName("第"+i+"个学生"); int blogCount=new java.util.Random().nextInt(5)+5;//日志个数的随机数 for(int t=0;t<blogCount;t++){//每个用户生成随机个数的日志对象 UserBlog ub=new UserBlog(); ub.setId(i*t);//每个UserBlog对象的唯一id; ub.setId_userInfo(i);//所属的用户id; ub.setTitle(us.getName()+"的第"+t+"篇日志"); ub.setContent("这是我的日志内容,我将要写"+t+"行"); //程序中生成创建日志的格式化时间 java.util.Date now=new java.util.Date(); java.text.SimpleDateFormat f=new java.text.SimpleDateFormat("yyyy年MM朋dd日hh:mm:ss"); String timeStr=f.format(now); ub.setCreateTime(timeStr); ub.setUserinfo(us);//日志对象所属的用户对象 //将这个日志对象装入所属用户对象的列表中: us.addBlog(ub); } //将生成的us对象放入到队列中 userList.add(us); } return userList; } } |
UserDao中只有一个方法,当这个方法调用时,生成模拟的用户对象和blog对象(在具体的应用中,这个方法应是从数据库或文件中提取数据,生成对象)。
最后,我们编写界面代码:显示一个JTree对象,JTree中的节点对应了UserInfo和UserBlog对象:
//JTree应用示例:简单日志管理系统 public class BlogManagerUI extends javax.swing.JFrame { public static void main(String[] args) { BlogManagerUI tj=new BlogManagerUI(); tj.init(); }
//初始化界面内容 public void init() { this.setTitle("东方标准JTree示例--日志管理"); this.setSize(300, 400); java.awt.FlowLayout fl = new java.awt.FlowLayout(); this.setLayout(fl); //创建用户列表后,就可以使用userList中的对象构造树: UserDao dao=new UserDao(); userList=dao.getAllUser(); // 将自己创建的树加到界面上: javax.swing.JTree tree = createTree(); this.add(tree); this.setDefaultCloseOperation(3); this.setVisible(true); } //创建一个自定义树 public javax.swing.JTree createTree() { // 创建默认树 javax.swing.JTree tree = new javax.swing.JTree(); // 首先,创建一个根节点: javax.swing.tree.DefaultMutableTreeNode rootNode = new javax.swing.tree.DefaultMutableTreeNode(); // 设定节点上的数据对象,节点显示标题则为设定对象的toString()值 rootNode.setUserObject("日志管理"); //取得要加载到树上的用户对象列表 for (int i = 0; i <userList.size(); i++) { DefaultMutableTreeNode teamNode = new DefaultMutableTreeNode(); //得到列表中每一个用户对象,设为树节点对象 UserInfo us=userList.get(i); teamNode.setUserObject(us); // 将组节点加到根节点上: rootNode.add(teamNode); //取得所属于这个用户的blog对象列表 List<UserBlog> blogList=us.getBlogList(); for (int t = 0; t <blogList.size(); t++) { DefaultMutableTreeNode userNode = new DefaultMutableTreeNode(); UserBlog ub=blogList.get(t);//从队列中得到blog对象 userNode.setUserObject(ub); // 将用户节点加到组节点上: teamNode.add(userNode); } // 创建树的Model对象,创建时传入根节点: javax.swing.tree.DefaultTreeModel dm = new DefaultTreeModel(rootNode); // 将模型设给树,树上显示的将上前面所加载的节点 tree.setModel(dm); } return tree; } //用户对象列表: private List<UserInfo> userList; }
接下来,我们应该给JTree加上弹出菜单实现Tree上节点对应对象的删改功能。 3.JTree节点的选中和信息获取在弹出菜单示例的那一节,我们己知道如何给组件加上弹出菜单,在这个基础上,要实现的就是当菜单事件发生时,实现对应的功能操作:从树上移除,增加或显示选中节点所含的对象的数据;并更新内存中UserInfo对象列表中的数据。首先,我们实现能显示用户选中的节点的数据对象:
以上代码,关键是在弹出菜单的事件处理中:当用户选中菜单时,得要选中的树上的节点,并取得这个节点所代表的对象,通过instanceof关键字比较,选中的是UserInfo对象的节点还是UserBlog对象的节点;在本例中,仅是将用户要执行的操作命令和选中对象的部分数据显示出来而己
接下来,我们就应真正的实现菜单上的功能: 4.JTree的编辑《日志管理实现》:在上例中,我们己可以得到选中的节点对象和节点内部的数据对象,接下来,要实现的是当选删除菜单时,将选中的节点从树上移掉;当点击添加和修改菜单时,应能弹出界面让用户实现修改和添加功能。请看如下代码:
|