Java Swing编程:JTree树

树这东西给用户的感觉极为方便,但给程序员带来很大的麻烦,它是swing中最麻烦的控件之一。树要弄的好非常麻烦,图标的美化,层次的划分,各种事件的处理。。。对于初学者来说,就不要太讲究样式,下面举个粗糙的例子,eg

 
 
  1. public class SimpleJTree    
  2. {  
  3.     JFrame jf = new JFrame("简单树");  
  4.  
  5.     JTree tree;  
  6.     //定义几个初始节点  
  7.     DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");   
  8.     DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");  
  9.     DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");  
  10.     DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");  
  11.     DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");  
  12.     DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");  
  13.     DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");  
  14.  
  15.     public void init()  
  16.     {  
  17.         //通过add方法建立树节点之间的父子关系  
  18.         guangdong.add(foshan);  
  19.         guangdong.add(shantou);  
  20.         guangxi.add(guilin);  
  21.         guangxi.add(nanning);  
  22.         root.add(guangdong);  
  23.         root.add(guangxi);  
  24.         //以根节点创建树  
  25.         tree = new JTree(root);  
  26.  
  27.         //默认连线  
  28.         //tree.putClientProperty("JTree.lineStyle" , "Angeled");  
  29.         //没有连线  
  30.         tree.putClientProperty("JTree.lineStyle" , "None");  
  31.         //水平分隔线  
  32.         //tree.putClientProperty("JTree.lineStyle" , "Horizontal");   
  33.  
  34.  
  35.         //设置是否显示根节点的“展开/折叠”图标,默认是false  
  36.         tree.setShowsRootHandles(true);  
  37.         //设置节点是否可见,默认是true  
  38.         tree.setRootVisible(true);  
  39.  
  40.         jf.add(new JScrollPane(tree));  
  41.         jf.pack();  
  42.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  43.         jf.setVisible(true);  
  44.     }  
  45.  
  46.     public static void main(String[] args)   
  47.     {  
  48.         new SimpleJTree().init();  
  49.     }  
  50. }  

拖动,编辑树节点也是树的基本功能,下面就在上面例子的基础上,加上这些功能,eg

 
 
  1. public class EditJTree  
  2. {  
  3.     JFrame jf;  
  4.  
  5.     JTree tree;  
  6.     //上面JTree对象对应的model  
  7.     DefaultTreeModel model;  
  8.       
  9.     //定义几个初始节点  
  10.     DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国");   
  11.     DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东");  
  12.     DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西");  
  13.     DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");  
  14.     DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头");  
  15.     DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");  
  16.     DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁");  
  17.  
  18.     //定义需要被拖动的TreePath  
  19.     TreePath movePath;  
  20.  
  21.     JButton addSiblingButton = new JButton("添加兄弟节点");  
  22.     JButton addChildButton = new JButton("添加子节点");  
  23.     JButton deleteButton = new JButton("删除节点");  
  24.     JButton editButton = new JButton("编辑当前节点");  
  25.  
  26.     public void init()  
  27.     {  
  28.         guangdong.add(foshan);  
  29.         guangdong.add(shantou);  
  30.         guangxi.add(guilin);  
  31.         guangxi.add(nanning);  
  32.         root.add(guangdong);  
  33.         root.add(guangxi);  
  34.           
  35.         jf = new JFrame("树");  
  36.         tree = new JTree(root);  
  37.         //获取JTree对应的TreeModel对象  
  38.         model = (DefaultTreeModel)tree.getModel();  
  39.         //设置JTree可编辑  
  40.         tree.setEditable(true);  
  41.         MouseListener ml = new MouseAdapter()   
  42.         {  
  43.             //按下鼠标时候获得被拖动的节点  
  44.             public void mousePressed(MouseEvent e)  
  45.             {  
  46.                 //如果需要唯一确定某个节点,必须通过TreePath来获取。  
  47.                 TreePath tp = tree.getPathForLocation(e.getX(), e.getY());  
  48.                 if (tp != null)  
  49.                 {  
  50.                     movePath = tp;  
  51.                 }  
  52.             }  
  53.             //鼠标松开时获得需要拖到哪个父节点  
  54.             public void mouseReleased(MouseEvent e)  
  55.             {  
  56.                 //根据鼠标松开时的TreePath来获取TreePath  
  57.                 TreePath tp = tree.getPathForLocation(e.getX(), e.getY());  
  58.  
  59.                 if (tp != null && movePath != null)  
  60.                 {  
  61.                     //阻止向子节点拖动  
  62.                     if (movePath.isDescendant(tp) && movePath != tp)  
  63.                     {  
  64.                         JOptionPane.showMessageDialog(jf, "目标节点是被移动节点的子节点,无法移动!",   
  65.                             "非法操作", JOptionPane.ERROR_MESSAGE );  
  66.                         return;  
  67.                     }  
  68.                     //既不是向子节点移动,而且鼠标按下、松开的不是同一个节点  
  69.                     else if (movePath != tp)  
  70.                     {  
  71.                         System.out.println(tp.getLastPathComponent());  
  72.                         //add方法可以先将原节点从原父节点删除,再添加到新父节点中  
  73.                         ((DefaultMutableTreeNode)tp.getLastPathComponent()).add(  
  74.                             (DefaultMutableTreeNode)movePath.getLastPathComponent());  
  75.                         movePath = null;  
  76.                         tree.updateUI();  
  77.                     }  
  78.                 }  
  79.             }  
  80.         };  
  81.         tree.addMouseListener(ml);  
  82.  
  83.         JPanel panel = new JPanel();  
  84.  
  85.         addSiblingButton.addActionListener(new ActionListener()  
  86.         {  
  87.             public void actionPerformed(ActionEvent event)  
  88.             {  
  89.                 //获取选中节点  
  90.                 DefaultMutableTreeNode selectedNode  
  91.                     = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();  
  92.                 //如果节点为空,直接返回  
  93.                 if (selectedNode == nullreturn;  
  94.                 //获取该选中节点的父节点  
  95.                 DefaultMutableTreeNode parent  
  96.                     = (DefaultMutableTreeNode)selectedNode.getParent();  
  97.                 //如果父节点为空,直接返回  
  98.                 if (parent == nullreturn;  
  99.                 //创建一个新节点  
  100.                 DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新节点");  
  101.                 //获取选中节点的选中索引  
  102.                 int selectedIndex = parent.getIndex(selectedNode);  
  103.                 //在选中位置插入新节点  
  104.                 model.insertNodeInto(newNode, parent, selectedIndex + 1);  
  105.                 //--------下面代码实现显示新节点(自动展开父节点)-------  
  106.                 //获取从根节点到新节点的所有节点  
  107.                 TreeNode[] nodes = model.getPathToRoot(newNode);  
  108.                 //使用指定的节点数组来创建TreePath  
  109.                 TreePath path = new TreePath(nodes);  
  110.                 //显示指定TreePath  
  111.                 tree.scrollPathToVisible(path);  
  112.             }  
  113.         });  
  114.         panel.add(addSiblingButton);  
  115.  
  116.         addChildButton.addActionListener(new ActionListener()  
  117.         {  
  118.             public void actionPerformed(ActionEvent event)  
  119.             {  
  120.                 //获取选中节点  
  121.                 DefaultMutableTreeNode selectedNode  
  122.                     = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();  
  123.                 //如果节点为空,直接返回  
  124.                 if (selectedNode == nullreturn;  
  125.                 //创建一个新节点  
  126.                 DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新节点");  
  127.                 //直接通过model来添加新节点,则无需通过调用JTree的updateUI方法  
  128.                 //model.insertNodeInto(newNode, selectedNode, selectedNode.getChildCount());  
  129.                 //直接通过节点添加新节点,则需要调用tree的updateUI方法  
  130.                 selectedNode.add(newNode);  
  131.                 //--------下面代码实现显示新节点(自动展开父节点)-------  
  132.                 TreeNode[] nodes = model.getPathToRoot(newNode);  
  133.                 TreePath path = new TreePath(nodes);  
  134.                 tree.scrollPathToVisible(path);  
  135.                 tree.updateUI();  
  136.             }  
  137.         });  
  138.         panel.add(addChildButton);  
  139.  
  140.         deleteButton.addActionListener(new ActionListener()  
  141.         {  
  142.             public void actionPerformed(ActionEvent event)  
  143.             {  
  144.                 DefaultMutableTreeNode selectedNode  
  145.                     = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();  
  146.                 if (selectedNode != null && selectedNode.getParent() != null)  
  147.                 {  
  148.                     //删除指定节点  
  149.                     model.removeNodeFromParent(selectedNode);  
  150.                 }  
  151.             }  
  152.         });  
  153.         panel.add(deleteButton);  
  154.  
  155.         editButton.addActionListener(new ActionListener()  
  156.         {  
  157.             public void actionPerformed(ActionEvent event)  
  158.             {  
  159.                 TreePath selectedPath = tree.getSelectionPath();  
  160.                 if (selectedPath != null)  
  161.                 {  
  162.                     //编辑选中节点  
  163.                     tree.startEditingAtPath(selectedPath);  
  164.                 }  
  165.             }  
  166.         });  
  167.         panel.add(editButton);  
  168.  
  169.         jf.add(new JScrollPane(tree));  
  170.         jf.add(panel , BorderLayout.SOUTH);  
  171.         jf.pack();  
  172.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  173.         jf.setVisible(true);  
  174.     }  
  175.  
  176.     public static void main(String[] args)   
  177.     {  
  178.         new EditJTree().init();  
  179.     }  
  180. }  

最后讲下如何修饰tree的图标,主要是通过拓展TreeCellRenderer来实现,eg

 
 
  1. public class ExtendsDefaultTreeCellRenderer    
  2. {  
  3.     JFrame jf = new JFrame("根据节点类型定义图标");  
  4.  
  5.     JTree tree;  
  6.     //定义几个初始节点  
  7.     DefaultMutableTreeNode root = new DefaultMutableTreeNode(  
  8.         new NodeData(DBObjectType.ROOT , "数据库导航"));   
  9.     DefaultMutableTreeNode salaryDb = new DefaultMutableTreeNode(  
  10.         new NodeData(DBObjectType.DATABASE , "公司工资数据库"));  
  11.     DefaultMutableTreeNode customerDb = new DefaultMutableTreeNode(  
  12.         new NodeData(DBObjectType.DATABASE , "公司客户数据库"));  
  13.     //定义salaryDb的两个子节点  
  14.     DefaultMutableTreeNode employee = new DefaultMutableTreeNode(  
  15.         new NodeData(DBObjectType.TABLE , "员工表"));  
  16.     DefaultMutableTreeNode attend = new DefaultMutableTreeNode(  
  17.         new NodeData(DBObjectType.TABLE , "考勤表"));  
  18.     //定义customerDb的一个子节点  
  19.     DefaultMutableTreeNode contact = new DefaultMutableTreeNode(  
  20.         new NodeData(DBObjectType.TABLE , "联系方式表"));  
  21.  
  22.     //定义employee的三个子节点  
  23.     DefaultMutableTreeNode id = new DefaultMutableTreeNode(  
  24.         new NodeData(DBObjectType.INDEX , "员工ID"));  
  25.     DefaultMutableTreeNode name = new DefaultMutableTreeNode(  
  26.         new NodeData(DBObjectType.COLUMN , "姓名"));  
  27.     DefaultMutableTreeNode gender = new DefaultMutableTreeNode(  
  28.         new NodeData(DBObjectType.COLUMN , "性别"));  
  29.  
  30.     public void init()throws Exception  
  31.     {  
  32.         //通过add方法建立树节点之间的父子关系  
  33.         root.add(salaryDb);  
  34.         root.add(customerDb);  
  35.         salaryDb.add(employee);  
  36.         salaryDb.add(attend);  
  37.         customerDb.add(contact);  
  38.         employee.add(id);  
  39.         employee.add(name);  
  40.         employee.add(gender);  
  41.         //以根节点创建树  
  42.         tree = new JTree(root);  
  43.           
  44.         //设置该JTree使用自定义的节点绘制器  
  45.         tree.setCellRenderer(new MyRenderer());  
  46.       
  47.         //设置是否显示根节点的“展开/折叠”图标,默认是false  
  48.         tree.setShowsRootHandles(true);  
  49.         //设置节点是否可见,默认是true  
  50.         tree.setRootVisible(true);  
  51.  
  52.         //设置使用Windows风格外观  
  53.         UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");  
  54.         //更新JTree的UI外观  
  55.         SwingUtilities.updateComponentTreeUI(tree);  
  56.  
  57.         jf.add(new JScrollPane(tree));  
  58.         jf.pack();  
  59.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  60.         jf.setVisible(true);  
  61.     }  
  62.  
  63.     public static void main(String[] args) throws Exception  
  64.     {  
  65.         new ExtendsDefaultTreeCellRenderer().init();  
  66.     }  
  67. }  
  68. //定义一个NodeData类,用于封装节点数据  
  69. class NodeData  
  70. {  
  71.     public int nodeType;  
  72.     public String nodeData;  
  73.     public NodeData(int nodeType , String nodeData)  
  74.     {  
  75.         this.nodeType = nodeType;  
  76.         this.nodeData = nodeData;  
  77.     }  
  78.     public String toString()  
  79.     {  
  80.         return nodeData;  
  81.     }  
  82. }  
  83. //定义一个接口,该接口里包含数据库对象类型的常量  
  84. interface DBObjectType  
  85. {  
  86.     int ROOT = 0;  
  87.     int DATABASE = 1;  
  88.     int TABLE = 2;  
  89.     int COLUMN = 3;  
  90.     int INDEX = 4;  
  91. }  
  92. class MyRenderer extends DefaultTreeCellRenderer  
  93. {  
  94.     //初始化5个图标  
  95.     ImageIcon rootIcon = new ImageIcon("icon/root.gif");  
  96.     ImageIcon databaseIcon = new ImageIcon("icon/database.gif");  
  97.     ImageIcon tableIcon = new ImageIcon("icon/table.gif");  
  98.     ImageIcon columnIcon = new ImageIcon("icon/column.gif");  
  99.     ImageIcon indexIcon = new ImageIcon("icon/index.gif");  
  100.  
  101.     public Component getTreeCellRendererComponent(JTree tree, Object value,  
  102.         boolean sel, boolean expanded,  boolean leaf, int row, boolean hasFocus)  
  103.     {  
  104.         //执行父类默认的节点绘制操作  
  105.         super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);  
  106.  
  107.         DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;  
  108.         NodeData data = (NodeData)node.getUserObject();  
  109.         //根据数据节点里的nodeType数据决定节点图标  
  110.         ImageIcon icon = null;  
  111.         switch(data.nodeType)  
  112.         {  
  113.             case DBObjectType.ROOT:  
  114.                 icon = rootIcon;  
  115.                 break;  
  116.             case DBObjectType.DATABASE:  
  117.                 icon = databaseIcon;  
  118.                 break;  
  119.             case DBObjectType.TABLE:  
  120.                 icon = tableIcon;  
  121.                 break;  
  122.             case DBObjectType.COLUMN:  
  123.                 icon = columnIcon;  
  124.                 break;  
  125.             case DBObjectType.INDEX:  
  126.                 icon = indexIcon;  
  127.                 break;  
  128.         }  
  129.         //改变图标  
  130.         this.setIcon(icon);  
  131.         return this;  
  132.     }  
目录 目录 1 (一) Spring 开发 Swing GUI 简介——依赖注入和富客户机 5 关于本教程 5 前提条件 6 Spring 和依赖注入概述 7 什么是 Spring 框架? 7 什么是依赖注入? 7 环境设置 7 选择编译环境 7 设置 Ant 8 通过 Ant 自动下载依赖软件 10 设置 Maven 10 通过 Maven 自动下载依赖软件 12 设置 Eclipse 13 下载依赖的 JAR 文件并在 Eclipse 的 classpath 中定义这种依赖性 15 创建 to-do 列表:基本的 Swing 和 Spring 应用程序设置 17 创建 MainFrame、Launcher 和 ToDo 类 17 创建 Spring app-context.xml bean 定义文件 19 运行应用程序 20 定义 bean 属性 21 创建 to-do 列表:创建一个可重用组件并在表中显示数据 23 创建一个可重用的面板 23 将 bean 组合在一起 24 添加一个表并重用这个面板 26 定义表模型 28 显示列表中的项 29 创建 to-do 列表:完成 —— 按钮和监听程序 31 创建按钮和监听程序 32 组合按钮和监听程序 35 Spring Rich Client Project 37 Spring Rich Client Project 概述 37 结束语 38 (二) 适用于各类Swing应用的通用数据验证模块 39 项目创建好后,加入类库: 41 然后写一个persistence bean: 41 Java代码 41 我称这个类为HibernateValidationUI,代码如下: 43 Java代码 43 类中用到的Java2DIconFactory代码如下: 47 Java代码 47 Factory类 49 Java代码 49 最后,我们可以编写一个Demo application来看看效果如何,代码如下: 51 Java代码 51 总结: 55 (三) 对JTree从创建到使用详解 56 (四) JTree的使用方法 57 JTreeDemo.java源程序 57 经验汇总 60 1. 初始化 60 2. 三个经常使用的取值函数 60 3. 根据node得到path: 60 4. 根据Path展开到该节点 60 5. 根据path设定该节点选定 61 6. 选中节点的方法 61 7. 滚动到可见位置 61 8. 给JTree添加右键弹出菜单 61 9. 关于JTree的展开 61 10. 如何遍历JTree 62 (五) JTree右键菜单实现编辑、添加、删除节点 63 Test.java源代码 63 (六) 功能齐全的JTree例子 66 TreeEditTest.java源代码 66 (七) JTree控件的使用 70 构造函数: 70 TreeModel接口 70 DefaultTreeModel缺省版本 71 TreeNode接口 71 TreeExpansionListener接口 71 TreeCellRenderer 72 例子: 73 (八) 如何为JTree添加右键菜单? 75 (九) 如何使JTextArea随着窗体的变化自动调整大小 76 TextAreaTest源代码 76 (十) JAVA swing编程JTree实现系统目录 77 FileTree1.java源代码 77 (十一) Java Swing中的JTree模型 85 Swing.tree包中的主要类名称实现 85 1. 构建模型 86 2. 结点 86 结构详细类图 86 2.1 TreeNode接口 86 2.2 MutableTreeNode接口 87 2.3 DefaultMutableTreeNode类 88 3. 编辑 88 3.1获得结点路径 88 3.2编辑结点 88 3.3视图显示 89 4. 查找 89 5. 绘制结点 90 (十二) JTree鼠标左键的双击事件选用那个监听器 91 MouseDemo.java源代码 92 (十三) JTree 92 JTree的构造函数: 93 JTreeDefaultDemo.java源代码 93 (十四) JTree 应用 96 Frame1.java源代码 96 MyDefaultTreeCellRenderer.java源代码 98 (十五) JTree控件 100 和节点的基本概念 100 有关JTree的类和接口 100 代码实例:构建一棵 101 相关语句解释 101 (十六) JTree应用示例——文件路径 103 AnimatedIconTreeExample.java源代码 103 //内部类NodeImageObserver.java源代码 105 //IconNodeRenderer.java源代码 106 //IconNode.java源代码 107 (十七) Swing 学习笔记 108 Swing API 包括18个公共包: 108 例程1.1 HelloWorldSwing.java 109 例程2.2 HelloWorldJFrame.java 110 (十八) 动态加载文件java程序 111 FileSystemTree.java源代码 112 //内部类 TreeWillExpandListenerImp.java 114 (十九) 向 Java 应用程序伸出援助之手——用 JavaHelp 2.0 构建下一个 Java 应用程序的帮助系统 115 入门 116 使用 HelpSet 117 HelpSet 数据文件 118 helpset 文件 118 maps 部分 119 view 部分 119 presentation 部分 120 implementation 部分 121 map 文件 121 导航文件 121 TOC 122 Index 122 Glossary 123 Favorites 123 主题文件 123 在 Java 应用程序中调用 JavaHelp 124 自定义外观 125 配置图标 125 基于文字的标签还是基于图像的标签? 125 要工具栏还是不要工具栏? 125 设置字体 126 使用展示窗口 127 <object> 标签 128 四种 activator 129 添加内容敏感的帮助 130 窗口级帮助 131 字段级帮助 131 屏幕级帮助 133 添加嵌入帮助 135 添加搜索功能 136 停用词 137 自定义停用词列表 137 合并 helpset 138 静态和动态合并 139 添加轻量级组件 141 基于服务器的帮助 144 设置 144 JavaHelp 服务器 bean 144 JavaScript 文件 145 JSP 文件 145 测试服务器端帮助 148 结束语 149
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值