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