Java Swing编程:JTree树

开发 后端
树这东西给用户的感觉极为方便,但给程序员带来很大的麻烦,它是swing中最麻烦的控件之一。树要弄的好非常麻烦,图标的美化,层次的划分,各种事件的处理。

树这东西给用户的感觉极为方便,但给程序员带来很大的麻烦,它是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.     }  

图标大家就自己搞几个吧,不搞也可以看到效果。明天我将讲下JTable,也是个麻烦的控件。

原文链接:http://blog.csdn.net/terryzero/article/details/3828045

【编辑推荐】

  1. Java Swing编程:微调控制器和列表框
  2. Java Swing编程:进度条和滑动条
  3. Java Swing编程:Applet和JApplet
  4. Java Swing编程:拖放功能
  5. Java Swing编程:特殊容器
责任编辑:林师授 来源: terryzero的博客
相关推荐

2009-07-10 18:06:59

JTree Swing

2009-07-15 10:52:13

JTree组件

2012-01-17 13:41:34

JavaSwing

2012-01-17 14:09:54

JavaSwing

2012-01-17 13:46:55

JavaSwing

2012-01-17 13:16:34

JavaSwing

2012-01-17 13:53:16

JavaSwing

2012-01-17 13:58:17

JavaSwing

2012-01-17 14:01:33

JavaSwing

2009-06-10 16:17:00

Netbeans JT初始化

2021-03-18 08:44:20

Java数据结构算法

2009-07-10 14:20:01

AcceleratorJava Swing

2009-07-10 11:45:44

Java Swing

2009-07-16 11:13:50

Java Swing

2009-07-15 13:48:26

Swing模型和渲染器

2009-07-10 13:09:53

.Net与Java S

2009-07-10 10:47:01

Java Swing

2021-04-07 09:26:37

Java数据结构算法

2009-07-10 15:10:02

Java Swing经

2009-07-15 15:35:59

Swing程序Swing性能
点赞
收藏

51CTO技术栈公众号