package day5_090306; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Enumeration; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; public class CheckboxNodeTree extends JFrame { private static final long serialVersionUID = 1L; public CheckboxNodeTree() { super("CheckboxTreeExample"); String[] strs = { "计算机", "数学", "软件设计", "数学分析", "Java", "C++", "离散数学" }; CheckboxTreeNode[] nodes = new CheckboxTreeNode[strs.length]; // 构建复选框节点 for (int i = 0; i < strs.length; i++) { nodes[i] = new CheckboxTreeNode(strs[i]); } nodes[0].add(nodes[1]); // 节点子父关系的描述 nodes[0].add(nodes[2]); nodes[1].add(nodes[3]); nodes[1].add(nodes[6]); nodes[2].add(nodes[4]); nodes[2].add(nodes[5]); JTree tree = new JTree(nodes[0]); tree.setCellRenderer(new CheckboxNodeTreeRenderer()); // 设置tree的显示方式(也就是渲染方式) tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION); tree.addMouseListener(new CheckboxNodeSelectedListener(tree)); // 为树注册鼠标监听器 JScrollPane scrollPane = new JScrollPane(tree); this.getContentPane().add(scrollPane, BorderLayout.CENTER); } class CheckboxNodeSelectedListener extends MouseAdapter { // 复选框节点监听器 JTree tree; public CheckboxNodeSelectedListener(JTree tree) { this.tree = tree; } @SuppressWarnings("unchecked") public void mouseClicked(MouseEvent e) { TreePath path = tree.getSelectionPath(); if (path != null) { CheckboxTreeNode node = (CheckboxTreeNode) path .getLastPathComponent(); CheckboxTreeNode pNode = node; boolean isSelected = node.isSelected(); if (node.isRoot()) { if (isSelected) {// 当前点击节点为根节点,且点击时的状态为勾选时 node.setCascadeSelected(false); collapseTreeNode(tree, node);// 折叠制定节点 ((DefaultTreeModel) tree.getModel()).nodeChanged(node); } else {// 当前点击节点为根节点,且点击时的状态为不勾选时 node.setCascadeSelected(true); notToSelected(tree, node, path); } } if (isSelected) {// 当前节点被点击时的状态为勾选时 node.setCascadeSelected(!isSelected);// 把当前节点以及其子节点设为不勾选 if (!node.isRoot()) {// 如果当前节点不是根节点就求其父节点 do { pNode = (CheckboxTreeNode) pNode.getParent(); Enumeration<CheckboxTreeNode> allChildNode; allChildNode = pNode.children();// 得到pNode所有的子节点 boolean allChildNotSelectedFlag = true; while (allChildNode.hasMoreElements()) { CheckboxTreeNode childNode = allChildNode .nextElement(); if (childNode.isSelected()) { allChildNotSelectedFlag = false; break; } } if (allChildNotSelectedFlag) {// pNode所有子节点都没有被勾选 pNode.setCascadeSelected(false); collapseTreeNode(tree, pNode);// 折叠制定节点 } ((DefaultTreeModel) tree.getModel()) .nodeChanged(pNode); } while (!pNode.isRoot());// 当pNode为根节点时停止循环 } } else {// 当前节点被点击时的状态为不勾选时 node.setCascadeSelected(!isSelected);// 把当前节点以及其子节点设为勾选 if (!node.isRoot()) { do { pNode = (CheckboxTreeNode) pNode.getParent(); pNode.setSelected(true); notToSelected(tree, pNode, path); } while (!pNode.isRoot()); } } } } } /* * 把点击状态从不不勾选-->勾选 */ private void notToSelected(JTree tree, CheckboxTreeNode node, TreePath path) { if (node.isSelected) { tree.expandPath(path); } else { tree.collapsePath(path); } ((DefaultTreeModel) tree.getModel()).nodeChanged(node); } public void collapseTreeNode(JTree tree, CheckboxTreeNode node) { if (node.isLeaf()) { return; } tree.collapsePath(new TreePath(((CheckboxTreeNode) node).getPath())); int n = node.getChildCount(); for (int i = 0; i < n; i++) { collapseTreeNode(tree, (CheckboxTreeNode) node.getChildAt(i)); } } public static void main(String[] args) { CheckboxNodeTree frame = new CheckboxNodeTree(); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.setSize(400, 300); frame.setVisible(true); } } class CheckboxNodeTreeRenderer extends JPanel implements TreeCellRenderer { private static final long serialVersionUID = 1L; protected JCheckBox check; // 自己定义的复选框 protected TreeLabel label; // 自己定义的树节点标签 public CheckboxNodeTreeRenderer() { // 构造函数 setLayout(null); add(check = new JCheckBox()); add(label = new TreeLabel()); } @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row, boolean hasFocus) { String stringValue = tree.convertValueToText(value, isSelected, expanded, leaf, row, hasFocus); this.setEnabled(tree.isEnabled()); check.setSelected(((CheckboxTreeNode) value).isSelected()); // 根据value的状态来设置按钮check的状态 label.setFont(tree.getFont()); label.setText(stringValue); label.setSelected(isSelected); label.setFocus(hasFocus); return this; } public Dimension getPreferredSize() { // 设置此组件的首选大小 Dimension d_check = check.getPreferredSize(); Dimension d_label = label.getPreferredSize(); return new Dimension(d_check.width + d_label.width, (d_check.height < d_label.height ? d_label.height : d_check.height)); } public void doLayout() { // 自定义布局 Dimension d_check = check.getPreferredSize(); Dimension d_label = label.getPreferredSize(); int y_check = 0; int y_label = 0; if (d_check.height < d_label.height) { y_check = (d_label.height - d_check.height) / 2; } else { y_label = (d_check.height - d_label.height) / 2; } check.setLocation(0, y_check); check.setBounds(0, y_check, d_check.width, d_check.height); label.setLocation(d_check.width, y_label); label.setBounds(d_check.width, y_label, d_label.width, d_label.height); } public class TreeLabel extends JLabel {// 自定义树节点标签 private static final long serialVersionUID = 1L; boolean isSelected; boolean hasFocus; public TreeLabel() { super(); } public void setSelected(boolean isSelected) { this.isSelected = isSelected; } public void setFocus(boolean hasFocus) { this.hasFocus = hasFocus; } } } /* * 功能:自定义节点描述,记录节点勾选状态 */ class CheckboxTreeNode extends DefaultMutableTreeNode { private static final long serialVersionUID = 1L; protected boolean isSelected; public CheckboxTreeNode() { super(null); } public CheckboxTreeNode(Object userObject) { super(userObject, true); } @SuppressWarnings("unchecked") public void setCascadeSelected(boolean isSelected) { this.isSelected = isSelected; if (children != null) { Enumeration e = children.elements(); while (e.hasMoreElements()) { CheckboxTreeNode node = (CheckboxTreeNode) e.nextElement(); node.setCascadeSelected(isSelected); } } } public void setSelected(boolean isSelected) { this.isSelected = isSelected; } public boolean isSelected() { return isSelected; } } 运行后结果: