John Jiang

          a cup of Java, cheers!
          https://github.com/johnshajiang/blog

             :: 首頁 ::  :: 聯系 :: 聚合  :: 管理 ::
            131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
          一個簡單的CheckBox Tree實現
          CheckBox Tree是一個十分常用的UI組件,它能使用戶方便地按特定規則勾選樹中的節點。本文實現了一種簡單的Checking規則:當勾選了某節點后,該節點的所有下級節點全部被勾選;當取消勾選某節點后,該節點的所有下級節點全部被取消勾選。(2009.08.05最后更新)

          實現CheckBox Tree的常用方法,就是使用JCheckBox作為JTree的TreeCellRendrer,并且需要實現特定的Checking規則來勾選/取消勾選CheckBox。

          1. 樹節點
          DefaultMutableTreeNode是最常用的TreeNode實現,此處我們將擴展這一實現--CheckBoxTreeNode,增加一個屬性isChecked,用于標識該節點是否要被勾選上。該類的完整代碼如下所示:
          public class CheckBoxTreeNode extends DefaultMutableTreeNode {

                 
          private static final long serialVersionUID = 3195314943599939279L;

                 
          private boolean isChecked = false;

                 
          public CheckBoxTreeNode(Object userObject) {
                         
          super(userObject);
                 }

                 
          public boolean isChecked() {
                         
          return isChecked;
                 }

                 
          public void setChecked(boolean isChecked) {
                         
          this.isChecked = isChecked;
                 }
          }

          2. 渲染器
          如本文開頭所述,我們將使用JCheckBox作為樹節點展現形式的渲染器,同時確定對節點進行勾選或取消勾選的規則。CheckBoxTreeCellRenderer本身即是一個JCheckBox,那么在實現getTreeCellRendererComponent方法時,只簡單地返回它自己的實例即可,而對于勾選或取消勾選的條件,則由CheckBoxTreeNode中的isChecked屬性來確定,完整的代碼如下所示:
          public class CheckBoxTreeCellRenderer extends JCheckBox implements TreeCellRenderer {

                 
          private static final long serialVersionUID = -6432020851855339311L;

                 
          public CheckBoxTreeCellRenderer() {
                         setOpaque(
          false);
                 }

                 
          public Component getTreeCellRendererComponent(JTree tree, Object value,
                                 
          boolean selected, boolean expanded, boolean leaf, int row,
                                 
          boolean hasFocus) {
                         CheckBoxTreeNode node 
          = ((CheckBoxTreeNode) value); // 獲取樹節點對象。
                         setText(node.toString()); // 設置CheckBox所展示的文本。

                         
          // 當樹節點被設置為勾選時,則該節點對應的CheckBox被勾選上;否則,取消勾選。
                         if (node.isChecked()) {
                                 setSelected(
          true);
                                 setForeground(Color.BLUE);
                         } 
          else {
                                 setSelected(
          false);
                                 setForeground(tree.getForeground());
                         }
                         
          return this;
                 }
          }

          3. 樹
          此處對JTree進行擴展,創建CheckBoxTree,該類只是為JTree添加了一個MouseListener,以偵聽鼠標選中樹節點后,如何設置勾選標記,并重繪樹。
          public class CheckBoxTree extends JTree {

                 
          private static final long serialVersionUID = -217950037507321241L;

                 
          public CheckBoxTree(TreeModel newModel) {
                         
          super(newModel);
                         addCheckingListener();
                 }

                 
          private void addCheckingListener() {
                         addMouseListener(
          new MouseAdapter() {

                                 @Override
                                 
          public void mousePressed(MouseEvent e) {
                                         
          int row = getRowForLocation(e.getX(), e.getY());
                                         TreePath treePath 
          = getPathForRow(row);
                                         
          if (treePath == null) {
                                                 
          return;
                                         }

                                         CheckBoxTreeNode node 
          = ((CheckBoxTreeNode) treePath.getLastPathComponent());
                                         
          boolean checking = !node.isChecked(); // 如果該節點已被勾選上,則此次將取消勾選;反之,亦反。
                                         checkNode(node, checking);

                                         repaint(); 
          // 重繪整棵樹。
                                 }

                                 
          // 遞歸地勾選或取消勾選指定節點及其所有下級節點的CheckBox。
                                 private void checkNode(CheckBoxTreeNode node, boolean checking) {
                                         node.setChecked(checking);
                                         
          if (!node.isLeaf()) {
                                                 Enumeration
          <CheckBoxTreeNode> children = node.children();
                                                 
          while (children.hasMoreElements()) {
                                                         checkNode(children.nextElement(), checking);
                                                 }
                                         }
                                 }
                         });
                 }
          }
          上述程序有兩個關鍵點:1. 設置當前節點及其子節點的勾選標記--checkNode;2. 重繪樹--repaint。調用repaint方法對樹進行繪制時,方法TreeCellRenderer.getTreeCellRendererComponent就會被調用,此時程序就會根據checkNode方法設定的isChecked來勾選或取消勾選對應的樹節點CheckBox。簡言之,就是先設置樹型數據中的勾選標記,然后渲染器再根據這些標記來渲染CheckBox。
          posted on 2009-08-05 21:10 John Jiang 閱讀(5424) 評論(3)  編輯  收藏 所屬分類: JavaSwingGUI原創

          評論

          # re: 一個簡單的CheckBox Tree實現(原)[未登錄] 2009-08-06 09:43 zeyuphoenix
          不要repaint(); // 重繪整棵樹
          這樣在很多時候都會造成cpu過高,或者莫名奇妙的繪制,我做項目遇到好幾次了
          都只能一行一行debug找,你在繼承DefaultMutableTreeNode 的類里把treenode的select方法寫的復雜一點 比如
          /**
          * set the node select.
          *
          * @param isSelected
          * node select or not.
          */
          public void setSelected(boolean isSelected) {
          this.isSelected = isSelected;

          if ((selectionMode == TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION)
          && (children != null)) {
          Enumeration<?> enumTemp = children.elements();
          while (enumTemp.hasMoreElements()) {
          MyTreeNode node = (MyTreeNode) enumTemp.nextElement();
          node.setSelected(isSelected);
          }
          }
          }
          然后在render里刷新就可以了,另外也不要繼承jcombox最好繼承jpanel這樣可以很好的以后做更復雜的添加  回復  更多評論
            

          # re: 一個簡單的CheckBox Tree實現(原) 2009-08-06 21:01 Sha Jiang
          > setSelected
          這個方法應該寫在何處?

          > 另外也不要繼承jcombox最好繼承jpanel這樣可以很好的以后做更復雜的添加
          我也知道這一點,只是在此處寫得簡單些罷了。  回復  更多評論
            

          # re: 一個簡單的CheckBox Tree實現(原) 2009-08-07 10:04 于翔
          還以為是JavaScript呢  回復  更多評論
            

          主站蜘蛛池模板: 府谷县| 玉溪市| 望江县| 红桥区| 杂多县| 拉孜县| 东山县| 新竹市| 通江县| 积石山| 锦州市| 台山市| 张掖市| 墨玉县| 灵宝市| 年辖:市辖区| 信宜市| 全州县| 察隅县| 湄潭县| 雅安市| 微山县| 扬中市| 历史| 张掖市| 荆门市| 晋中市| 绿春县| 获嘉县| 屏东市| 南宁市| 朝阳市| 荃湾区| 汶上县| 称多县| 葵青区| 同江市| 长葛市| 东莞市| 旺苍县| 太保市|