程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java Swing編程:JTree樹

Java Swing編程:JTree樹

編輯:關於JAVA

樹這東西給用戶的感覺極為方便,但給程序員帶來很大的麻煩,它是swing中最麻煩的控件之一。樹要弄的好非常麻煩,圖標的美化,層次的劃分,各種事件的處理。。。對於初學者來說,就不要太講究樣式,下面舉個粗糙的例子,eg

  1. public class SimpleJTree
  2. {
  3. JFrame jf = new JFrame("簡單樹");
  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. public void init()
  14. {
  15. //通過add方法建立樹節點之間的父子關系
  16. guangdong.add(foshan);
  17. guangdong.add(shantou);
  18. guangxi.add(guilin);
  19. guangxi.add(nanning);
  20. root.add(guangdong);
  21. root.add(guangxi);
  22. //以根節點創建樹
  23. tree = new JTree(root);
  24. //默認連線
  25. //tree.putClIEntProperty("JTree.lineStyle" , "Angeled");
  26. //沒有連線
  27. tree.putClIEntProperty("JTree.lineStyle" , "None");
  28. //水平分隔線
  29. //tree.putClIEntProperty("JTree.lineStyle" , "Horizontal");
  30. //設置是否顯示根節點的“展開/折疊”圖標,默認是false
  31. tree.setShowsRootHandles(true);
  32. //設置節點是否可見,默認是true
  33. tree.setRootVisible(true);
  34. jf.add(new JScrollPane(tree));
  35. jf.pack();
  36. jf.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
  37. jf.setVisible(true);
  38. }
  39. public static void main(String[] args)
  40. {
  41. new SimpleJTree().init();
  42. }
  43. }

拖動,編輯樹節點也是樹的基本功能,下面就在上面例子的基礎上,加上這些功能,eg

  1. public class EditJTree
  2. {
  3. JFrame jf;
  4. JTree tree;
  5. //上面JTree對象對應的model
  6. DefaultTreeModel model;
  7. //定義幾個初始節點
  8. DefaultMutableTreeNode root = new DefaultMutableTreeNode("中國");
  9. DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("廣東");
  10. DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("廣西");
  11. DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山");
  12. DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕頭");
  13. DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林");
  14. DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南寧");
  15. //定義需要被拖動的TreePath
  16. TreePath movePath;
  17. JButton addSiblingButton = new JButton("添加兄弟節點");
  18. JButton addChildButton = new JButton("添加子節點");
  19. JButton deleteButton = new JButton("刪除節點");
  20. JButton editButton = new JButton("編輯當前節點");
  21. public void init()
  22. {
  23. guangdong.add(foshan);
  24. guangdong.add(shantou);
  25. guangxi.add(guilin);
  26. guangxi.add(nanning);
  27. root.add(guangdong);
  28. root.add(guangxi);
  29. jf = new JFrame("樹");
  30. tree = new JTree(root);
  31. //獲取JTree對應的TreeModel對象
  32. model = (DefaultTreeModel)tree.getModel();
  33. //設置JTree可編輯
  34. tree.setEditable(true);
  35. MouseListener ml = new MouseAdapter()
  36. {
  37. //按下鼠標時候獲得被拖動的節點
  38. public void mousePressed(MouseEvent e)
  39. {
  40. //如果需要唯一確定某個節點,必須通過TreePath來獲取。
  41. TreePath tp = tree.getPathForLocation(e.getX(), e.getY());
  42. if (tp != null)
  43. {
  44. movePath = tp;
  45. }
  46. }
  47. //鼠標松開時獲得需要拖到哪個父節點
  48. public void mouseReleased(MouseEvent e)
  49. {
  50. //根據鼠標松開時的TreePath來獲取TreePath
  51. TreePath tp = tree.getPathForLocation(e.getX(), e.getY());
  52. if (tp != null && movePath != null)
  53. {
  54. //阻止向子節點拖動
  55. if (movePath.isDescendant(tp) && movePath != tp)
  56. {
  57. JOptionPane.showMessageDialog(jf, "目標節點是被移動節點的子節點,無法移動!",
  58. "非法操作", JOptionPane.ERROR_MESSAGE );
  59. return;
  60. }
  61. //既不是向子節點移動,而且鼠標按下、松開的不是同一個節點
  62. else if (movePath != tp)
  63. {
  64. System.out.println(tp.getLastPathComponent());
  65. //add方法可以先將原節點從原父節點刪除,再添加到新父節點中
  66. ((DefaultMutableTreeNode)tp.getLastPathComponent()).add(
  67. (DefaultMutableTreeNode)movePath.getLastPathComponent());
  68. movePath = null;
  69. tree.updateUI();
  70. }
  71. }
  72. }
  73. };
  74. tree.addMouseListener(ml);
  75. JPanel panel = new JPanel();
  76. addSiblingButton.addActionListener(new ActionListener()
  77. {
  78. public void actionPerformed(ActionEvent event)
  79. {
  80. //獲取選中節點
  81. DefaultMutableTreeNode selectedNode
  82. = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
  83. //如果節點為空,直接返回
  84. if (selectedNode == null) return;
  85. //獲取該選中節點的父節點
  86. DefaultMutableTreeNode parent
  87. = (DefaultMutableTreeNode)selectedNode.getParent();
  88. //如果父節點為空,直接返回
  89. if (parent == null) return;
  90. //創建一個新節點
  91. DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新節點");
  92. //獲取選中節點的選中索引
  93. int selectedIndex = parent.getIndex(selectedNode);
  94. //在選中位置插入新節點
  95. model.insertNodeInto(newNode, parent, selectedIndex + 1);
  96. //--------下面代碼實現顯示新節點(自動展開父節點)-------
  97. //獲取從根節點到新節點的所有節點
  98. TreeNode[] nodes = model.getPathToRoot(newNode);
  99. //使用指定的節點數組來創建TreePath
  100. TreePath path = new TreePath(nodes);
  101. //顯示指定TreePath
  102. tree.scrollPathToVisible(path);
  103. }
  104. });
  105. panel.add(addSiblingButton);
  106. addChildButton.addActionListener(new ActionListener()
  107. {
  108. public void actionPerformed(ActionEvent event)
  109. {
  110. //獲取選中節點
  111. DefaultMutableTreeNode selectedNode
  112. = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
  113. //如果節點為空,直接返回
  114. if (selectedNode == null) return;
  115. //創建一個新節點
  116. DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新節點");
  117. //直接通過model來添加新節點,則無需通過調用JTree的updateUI方法
  118. //model.insertNodeInto(newNode, selectedNode, selectedNode.getChildCount());
  119. //直接通過節點添加新節點,則需要調用tree的updateUI方法
  120. selectedNode.add(newNode);
  121. //--------下面代碼實現顯示新節點(自動展開父節點)-------
  122. TreeNode[] nodes = model.getPathToRoot(newNode);
  123. TreePath path = new TreePath(nodes);
  124. tree.scrollPathToVisible(path);
  125. tree.updateUI();
  126. }
  127. });
  128. panel.add(addChildButton);
  129. deleteButton.addActionListener(new ActionListener()
  130. {
  131. public void actionPerformed(ActionEvent event)
  132. {
  133. DefaultMutableTreeNode selectedNode
  134. = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
  135. if (selectedNode != null && selectedNode.getParent() != null)
  136. {
  137. //刪除指定節點
  138. model.removeNodeFromParent(selectedNode);
  139. }
  140. }
  141. });
  142. panel.add(deleteButton);
  143. editButton.addActionListener(new ActionListener()
  144. {
  145. public void actionPerformed(ActionEvent event)
  146. {
  147. TreePath selectedPath = tree.getSelectionPath();
  148. if (selectedPath != null)
  149. {
  150. //編輯選中節點
  151. tree.startEditingAtPath(selectedPath);
  152. }
  153. }
  154. });
  155. panel.add(editButton);
  156. jf.add(new JScrollPane(tree));
  157. jf.add(panel , BorderLayout.SOUTH);
  158. jf.pack();
  159. jf.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
  160. jf.setVisible(true);
  161. }
  162. public static void main(String[] args)
  163. {
  164. new EditJTree().init();
  165. }
  166. }

最後講下如何修飾tree的圖標,主要是通過拓展TreeCellRenderer來實現,eg

  1. public class ExtendsDefaultTreeCellRenderer
  2. {
  3. JFrame jf = new JFrame("根據節點類型定義圖標");
  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. //定義employee的三個子節點
  21. DefaultMutableTreeNode id = new DefaultMutableTreeNode(
  22. new NodeData(DBObjectType.INDEX , "員工ID"));
  23. DefaultMutableTreeNode name = new DefaultMutableTreeNode(
  24. new NodeData(DBObjectType.COLUMN , "姓名"));
  25. DefaultMutableTreeNode gender = new DefaultMutableTreeNode(
  26. new NodeData(DBObjectType.COLUMN , "性別"));
  27. public void init()throws Exception
  28. {
  29. //通過add方法建立樹節點之間的父子關系
  30. root.add(salaryDb);
  31. root.add(customerDb);
  32. salaryDb.add(employee);
  33. salaryDb.add(attend);
  34. customerDb.add(contact);
  35. employee.add(id);
  36. employee.add(name);
  37. employee.add(gender);
  38. //以根節點創建樹
  39. tree = new JTree(root);
  40. //設置該JTree使用自定義的節點繪制器
  41. tree.setCellRenderer(new MyRenderer());
  42. //設置是否顯示根節點的“展開/折疊”圖標,默認是false
  43. tree.setShowsRootHandles(true);
  44. //設置節點是否可見,默認是true
  45. tree.setRootVisible(true);
  46. //設置使用Windows風格外觀
  47. UIManager.setLookAndFeel("com.sun.Java.swing.plaf.windows.WindowsLookAndFeel");
  48. //更新JTree的UI外觀
  49. SwingUtilitIEs.updateComponentTreeUI(tree);
  50. jf.add(new JScrollPane(tree));
  51. jf.pack();
  52. jf.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
  53. jf.setVisible(true);
  54. }
  55. public static void main(String[] args) throws Exception
  56. {
  57. new ExtendsDefaultTreeCellRenderer().init();
  58. }
  59. }
  60. //定義一個NodeData類,用於封裝節點數據
  61. class NodeData
  62. {
  63. public int nodeType;
  64. public String nodeData;
  65. public NodeData(int nodeType , String nodeData)
  66. {
  67. this.nodeType = nodeType;
  68. this.nodeData = nodeData;
  69. }
  70. public String toString()
  71. {
  72. return nodeData;
  73. }
  74. }
  75. //定義一個接口,該接口裡包含數據庫對象類型的常量
  76. interface DBObjectType
  77. {
  78. int ROOT = 0;
  79. int DATABASE = 1;
  80. int TABLE = 2;
  81. int COLUMN = 3;
  82. int INDEX = 4;
  83. }
  84. class MyRenderer extends DefaultTreeCellRenderer
  85. {
  86. //初始化5個圖標
  87. ImageIcon rootIcon = new ImageIcon("icon/root.gif");
  88. ImageIcon databaseIcon = new ImageIcon("icon/database.gif");
  89. ImageIcon tableIcon = new ImageIcon("icon/table.gif");
  90. ImageIcon columnIcon = new ImageIcon("icon/column.gif");
  91. ImageIcon indexIcon = new ImageIcon("icon/index.gif");
  92. public Component getTreeCellRendererComponent(JTree tree, Object value,
  93. boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus)
  94. {
  95. //執行父類默認的節點繪制操作
  96. super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
  97. DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
  98. NodeData data = (NodeData)node.getUserObject();
  99. //根據數據節點裡的nodeType數據決定節點圖標
  100. ImageIcon icon = null;
  101. switch(data.nodeType)
  102. {
  103. case DBObjectType.ROOT:
  104. icon = rootIcon;
  105. break;
  106. case DBObjectType.DATABASE:
  107. icon = databaseIcon;
  108. break;
  109. case DBObjectType.TABLE:
  110. icon = tableIcon;
  111. break;
  112. case DBObjectType.COLUMN:
  113. icon = columnIcon;
  114. break;
  115. case DBObjectType.INDEX:
  116. icon = indexIcon;
  117. break;
  118. }
  119. //改變圖標
  120. this.setIcon(icon);
  121. return this;
  122. }
  123. }

圖標大家就自己搞幾個吧,不搞也可以看到效果。明天我將講下JTable,也是個麻煩的控件。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved