现在的位置: 首页 > 综合 > 正文

疯狂JAVA讲义—第十二章:Swing编程(七)JTree树

2013年08月14日 ⁄ 综合 ⁄ 共 20125字 ⁄ 字号 评论关闭

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

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

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

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

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

  1. public class ExtendsDefaultTreeCellRenderer   
  2.     JFrame jf = new JFrame("根据节点类型定义图标"); 
  3.  
  4.     JTree tree; 
  5.     //定义几个初始节点 
  6.     DefaultMutableTreeNode root = new DefaultMutableTreeNode( 
  7.         new NodeData(DBObjectType.ROOT ,
    "数据库导航"));  
  8.     DefaultMutableTreeNode salaryDb =
    new
    DefaultMutableTreeNode( 
  9.         new NodeData(DBObjectType.DATABASE ,
    "公司工资数据库")); 
  10.     DefaultMutableTreeNode customerDb =
    new
    DefaultMutableTreeNode( 
  11.         new NodeData(DBObjectType.DATABASE ,
    "公司客户数据库")); 
  12.     //定义salaryDb的两个子节点 
  13.     DefaultMutableTreeNode employee = new DefaultMutableTreeNode( 
  14.         new NodeData(DBObjectType.TABLE ,
    "员工表")); 
  15.     DefaultMutableTreeNode attend = new DefaultMutableTreeNode( 
  16.         new NodeData(DBObjectType.TABLE ,
    "考勤表")); 
  17.     //定义customerDb的一个子节点 
  18.     DefaultMutableTreeNode contact =
    new
    DefaultMutableTreeNode( 
  19.         new NodeData(DBObjectType.TABLE ,
    "联系方式表")); 
  20.  
  21.     //定义employee的三个子节点 
  22.     DefaultMutableTreeNode id = new DefaultMutableTreeNode( 
  23.         new NodeData(DBObjectType.INDEX ,
    "员工ID")); 
  24.     DefaultMutableTreeNode name = new DefaultMutableTreeNode( 
  25.         new NodeData(DBObjectType.COLUMN ,
    "姓名")); 
  26.     DefaultMutableTreeNode gender = new DefaultMutableTreeNode( 
  27.         new NodeData(DBObjectType.COLUMN ,
    "性别")); 
  28.  
  29.     public void init()throws Exception 
  30.     { 
  31.         //通过add方法建立树节点之间的父子关系 
  32.         root.add(salaryDb); 
  33.         root.add(customerDb); 
  34.         salaryDb.add(employee); 
  35.         salaryDb.add(attend); 
  36.         customerDb.add(contact); 
  37.         employee.add(id); 
  38.         employee.add(name); 
  39.         employee.add(gender); 
  40.         //以根节点创建树 
  41.         tree = new JTree(root); 
  42.          
  43.         //设置该JTree使用自定义的节点绘制器 
  44.         tree.setCellRenderer(new MyRenderer()); 
  45.      
  46.         //设置是否显示根节点的“展开/折叠”图标,默认是false 
  47.         tree.setShowsRootHandles(true); 
  48.         //设置节点是否可见,默认是true 
  49.         tree.setRootVisible(true); 
  50.  
  51.         //设置使用Windows风格外观 
  52.         UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); 
  53.         //更新JTree的UI外观 
  54.         SwingUtilities.updateComponentTreeUI(tree); 
  55.  
  56.         jf.add(new JScrollPane(tree)); 
  57.         jf.pack(); 
  58.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
  59.         jf.setVisible(true); 
  60.     } 
  61.  
  62.     public static
    void main(String[] args) throws Exception 
  63.     { 
  64.         new ExtendsDefaultTreeCellRenderer().init(); 
  65.     } 
  66. //定义一个NodeData类,用于封装节点数据 
  67. class NodeData 
  68.     public int nodeType; 
  69.     public String nodeData; 
  70.     public NodeData(int nodeType , String nodeData) 
  71.     { 
  72.         this.nodeType = nodeType; 
  73.         this.nodeData = nodeData; 
  74.     } 
  75.     public String toString() 
  76.     { 
  77.         return nodeData; 
  78.     } 
  79. //定义一个接口,该接口里包含数据库对象类型的常量 
  80. interface DBObjectType 
  81.     int ROOT = 0
  82.     int DATABASE =
    1
  83.     int TABLE = 2
  84.     int COLUMN =
    3
  85.     int INDEX = 4
  86. class MyRenderer extends DefaultTreeCellRenderer 
  87.     //初始化5个图标 
  88.     ImageIcon rootIcon = new ImageIcon("icon/root.gif"); 
  89.     ImageIcon databaseIcon = new ImageIcon("icon/database.gif"); 
  90.     ImageIcon tableIcon = new ImageIcon("icon/table.gif"); 
  91.     ImageIcon columnIcon = new ImageIcon("icon/column.gif"); 
  92.     ImageIcon indexIcon = new ImageIcon("icon/index.gif"); 
  93.  
  94.     public Component getTreeCellRendererComponent(JTree tree, Object value, 
  95.         boolean sel, boolean expanded, 
    boolean leaf, int row,
    boolean hasFocus) 
  96.     { 
  97.         //执行父类默认的节点绘制操作 
  98.         super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); 
  99.  
  100.         DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; 
  101.         NodeData data = (NodeData)node.getUserObject(); 
  102.         //根据数据节点里的nodeType数据决定节点图标 
  103.         ImageIcon icon = null
  104.         switch(data.nodeType) 
  105.         { 
  106.             case DBObjectType.ROOT: 
  107.                 icon = rootIcon; 
  108.                 break
  109.             case DBObjectType.DATABASE: 
  110.                 icon = databaseIcon; 
  111.                 break
  112.             case DBObjectType.TABLE: 
  113.                 icon = tableIcon; 
  114.                 break
  115.             case DBObjectType.COLUMN: 
  116.                 icon = columnIcon; 
  117.                 break
  118.             case DBObjectType.INDEX: 
  119.                 icon = indexIcon; 
  120.                 break
  121.         } 
  122.         //改变图标 
  123.         this.setIcon(icon); 
  124.         return this
  125.     } 

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

 

抱歉!评论已关闭.