John Jiang

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

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

          實(shí)現(xiàn)CheckBox Tree的常用方法,就是使用JCheckBox作為JTree的TreeCellRendrer,并且需要實(shí)現(xiàn)特定的Checking規(guī)則來勾選/取消勾選CheckBox。

          1. 樹節(jié)點(diǎn)
          DefaultMutableTreeNode是最常用的TreeNode實(shí)現(xiàn),此處我們將擴(kuò)展這一實(shí)現(xiàn)--CheckBoxTreeNode,增加一個屬性isChecked,用于標(biāo)識該節(jié)點(diǎn)是否要被勾選上。該類的完整代碼如下所示:
          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作為樹節(jié)點(diǎn)展現(xiàn)形式的渲染器,同時確定對節(jié)點(diǎn)進(jìn)行勾選或取消勾選的規(guī)則。CheckBoxTreeCellRenderer本身即是一個JCheckBox,那么在實(shí)現(xiàn)getTreeCellRendererComponent方法時,只簡單地返回它自己的實(shí)例即可,而對于勾選或取消勾選的條件,則由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); // 獲取樹節(jié)點(diǎn)對象。
                         setText(node.toString()); // 設(shè)置CheckBox所展示的文本。

                         
          // 當(dāng)樹節(jié)點(diǎn)被設(shè)置為勾選時,則該節(jié)點(diǎn)對應(yīng)的CheckBox被勾選上;否則,取消勾選。
                         if (node.isChecked()) {
                                 setSelected(
          true);
                                 setForeground(Color.BLUE);
                         } 
          else {
                                 setSelected(
          false);
                                 setForeground(tree.getForeground());
                         }
                         
          return this;
                 }
          }

          3. 樹
          此處對JTree進(jìn)行擴(kuò)展,創(chuàng)建CheckBoxTree,該類只是為JTree添加了一個MouseListener,以偵聽鼠標(biāo)選中樹節(jié)點(diǎn)后,如何設(shè)置勾選標(biāo)記,并重繪樹。
          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(); // 如果該節(jié)點(diǎn)已被勾選上,則此次將取消勾選;反之,亦反。
                                         checkNode(node, checking);

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

                                 
          // 遞歸地勾選或取消勾選指定節(jié)點(diǎn)及其所有下級節(jié)點(diǎn)的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);
                                                 }
                                         }
                                 }
                         });
                 }
          }
          上述程序有兩個關(guān)鍵點(diǎn):1. 設(shè)置當(dāng)前節(jié)點(diǎn)及其子節(jié)點(diǎn)的勾選標(biāo)記--checkNode;2. 重繪樹--repaint。調(diào)用repaint方法對樹進(jìn)行繪制時,方法TreeCellRenderer.getTreeCellRendererComponent就會被調(diào)用,此時程序就會根據(jù)checkNode方法設(shè)定的isChecked來勾選或取消勾選對應(yīng)的樹節(jié)點(diǎn)CheckBox。簡言之,就是先設(shè)置樹型數(shù)據(jù)中的勾選標(biāo)記,然后渲染器再根據(jù)這些標(biāo)記來渲染CheckBox。
          posted on 2009-08-05 21:10 John Jiang 閱讀(5424) 評論(3)  編輯  收藏 所屬分類: JavaSwing 、GUI 、原創(chuàng)

          評論

          # re: 一個簡單的CheckBox Tree實(shí)現(xiàn)(原)[未登錄] 2009-08-06 09:43 zeyuphoenix
          不要repaint(); // 重繪整棵樹
          這樣在很多時候都會造成cpu過高,或者莫名奇妙的繪制,我做項(xiàng)目遇到好幾次了
          都只能一行一行debug找,你在繼承DefaultMutableTreeNode 的類里把treenode的select方法寫的復(fù)雜一點(diǎn) 比如
          /**
          * 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這樣可以很好的以后做更復(fù)雜的添加  回復(fù)  更多評論
            

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

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

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

          主站蜘蛛池模板: 区。| 高邮市| 昭觉县| 鄂尔多斯市| 洮南市| 孟州市| 台南县| 札达县| 宁河县| 青海省| 苍南县| 商丘市| 腾冲县| 皮山县| 伊金霍洛旗| 松滋市| 桐柏县| 绵阳市| 合水县| 大方县| 南部县| 德兴市| 遂昌县| 兴安盟| 广宗县| 乌兰察布市| 衢州市| 西昌市| 塔河县| 莎车县| 临沂市| 曲阳县| 莆田市| 子长县| 肃宁县| 辽中县| 青阳县| 宁明县| 托里县| 宁河县| 清水河县|