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 阅读(5371) 评论(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呢  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: