带CheckBox的JTree

public class TreePanel extends JPanel {
	private CheckboxTreeNode node;

	private JTree tree;

   private CheckboxTreeNode[] nodes;

	public CheckboxTreeNode[] getNodes() {
		return nodes;
	}

	public void setNodes(CheckboxTreeNode[] nodes) {
		this.nodes = nodes;
	}
	
	public void clearNodes(){
		node.removeAllChildren();
		node.setSelected(false);
	}

        public TreePanel(){

                node = new CheckboxTreeNode("顶级节点");
		

		String[] strs = { "二级节点","二级节点1","三级节点" };

		CheckboxTreeNode[] nodes = new CheckboxTreeNode[strs.length]; // 构建复选框节点

		for (int i = 0; i < strs.length; i++) {
			nodes[i] = new CheckboxTreeNode(strs[i]);
		}
                //节点子父关系的描述
		nodes[1].add(nodes[2]);
		node.add(nodes[0]);
		node.add(nodes[1]);

                //得到所选择的节点
                //String str = node.getUserObject().toString();
                tree = new JTree(node);
		tree.setCellRenderer(new CheckboxNodeTreeRenderer()); // 设置tree的显示方式(也就是渲染方式)
		tree.getSelectionModel().setSelectionMode(
				TreeSelectionModel.SINGLE_TREE_SELECTION);
		tree.addMouseListener(new CheckboxNodeSelectedListener(tree)); // 为树注册鼠标监听器

        }

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)
			throws UnsupportedLookAndFeelException {

		
		 UIManager.setLookAndFeel( new WindowsLookAndFeel() ) ;
		 TreePanel frame = new TreePanel();
		 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);
		setBackground(Color.WHITE);
		check.setBackground(Color.WHITE);
		return this;
	}
	@Override
	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));
	}
	@Override
	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);
		//改变checkbox大小
		check.setBounds(0, y_check, d_check.width, d_check.height-2);
		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;
	}
}

  如果需要动态加载节点数据,单独开设线程处理数据,并依靠javax.swing.SwingUtilities.invokeLater改变界面效果。invokeLater参考: http://www.iteye.com/topic/468236

你可能感兴趣的:(swing,ITeye)