我用swing写了一个树,实现的功能就是传入一个放着map的list,根据这个list生成树,树的每个节点是一个HashMap,根据map里面的一个dm(代码)和fbdm(父辈代码)来组织树的层次结构,比如,a节点的代码是1,b节点的父辈代码是1,c节点的父辈代码也是1,那么b节点和c节点就作为a节点的子节点加到a节点下面,我现在遇到的问题是怎么递归这个节点,我写的只能做一层树结构,比如把b和c节点加到a下面我已经加成功了,但我还想把d节点加到c几点下就不行了,请高手帮我看看递归算法,不胜感激!写完马上给充50QB作为报酬,或是50RMB也行,谢谢!
代码如下:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;import javax.swing.Icon;
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.UIManager;
import javax.swing.plaf.ColorUIResource;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
public class TreeExample extends JFrame {
private static final long serialVersionUID = 1L;
JTree tree;
String title;
ArrayList list;
DefaultTreeModel treeModel = null;
/*
* 不带多选的tree构造函数
*/
public TreeExample(String title,ArrayList list) {
super(title);
this.title = title;
this.list = list;
createTree(list);
tree.setCellRenderer(applyTreeCellRenderer);
treeModel = (DefaultTreeModel)tree.getModel();
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addMouseListener(new NodeSelectionListener(tree));
JScrollPane sp = new JScrollPane(tree);
JPanel panel = new JPanel(new BorderLayout());
getContentPane().add(sp, BorderLayout.CENTER);
getContentPane().add(panel, BorderLayout.EAST);
}
/*
* 带多选的tree构造函数
*/
public TreeExample(String title,ArrayList list,boolean ischeck) {
super(title);
this.title = title;
this.list = list;
createTree(list);
tree.setCellRenderer(new CheckRenderer());
treeModel = (DefaultTreeModel)tree.getModel();
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addMouseListener(new NodeSelectionListener(tree));
JScrollPane sp = new JScrollPane(tree);
JPanel panel = new JPanel(new BorderLayout());
getContentPane().add(sp, BorderLayout.CENTER);
getContentPane().add(panel, BorderLayout.EAST);
}
/*
* 将对象存在,不带check的tree节点上,显示名称
*/
代码如下:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;import javax.swing.Icon;
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.UIManager;
import javax.swing.plaf.ColorUIResource;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
public class TreeExample extends JFrame {
private static final long serialVersionUID = 1L;
JTree tree;
String title;
ArrayList list;
DefaultTreeModel treeModel = null;
/*
* 不带多选的tree构造函数
*/
public TreeExample(String title,ArrayList list) {
super(title);
this.title = title;
this.list = list;
createTree(list);
tree.setCellRenderer(applyTreeCellRenderer);
treeModel = (DefaultTreeModel)tree.getModel();
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addMouseListener(new NodeSelectionListener(tree));
JScrollPane sp = new JScrollPane(tree);
JPanel panel = new JPanel(new BorderLayout());
getContentPane().add(sp, BorderLayout.CENTER);
getContentPane().add(panel, BorderLayout.EAST);
}
/*
* 带多选的tree构造函数
*/
public TreeExample(String title,ArrayList list,boolean ischeck) {
super(title);
this.title = title;
this.list = list;
createTree(list);
tree.setCellRenderer(new CheckRenderer());
treeModel = (DefaultTreeModel)tree.getModel();
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.addMouseListener(new NodeSelectionListener(tree));
JScrollPane sp = new JScrollPane(tree);
JPanel panel = new JPanel(new BorderLayout());
getContentPane().add(sp, BorderLayout.CENTER);
getContentPane().add(panel, BorderLayout.EAST);
}
/*
* 将对象存在,不带check的tree节点上,显示名称
*/
/*
* 将对象存在,不带check的tree节点上,显示名称
*/
private DefaultTreeCellRenderer applyTreeCellRenderer = new DefaultTreeCellRenderer() {
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
Object userObj = treeNode.getUserObject(); if (userObj instanceof HashMap) {
this.setIcon(null);
this.setText((String) ((HashMap) userObj).get("mc"));
}
return this;
}
};
/*
* 循环list生成树节点,问题就出在这里
*/
public void createTree(ArrayList ll){
HashMap map = null ;
CheckNode[] nodes = new CheckNode[ll.size()];
for(int i=0;i<nodes.length;i++){
map = (HashMap) ll.get(i);
nodes[i] = new CheckNode(map);
ArrayList l = getsubtree(map);
for(int j = 0;j<l.size();j++){
HashMap map2 = (HashMap) l.get(j);
CheckNode node = new CheckNode(map2);
if(node!=null){
nodes[i].add(node);
}
}
if(l!=null&&l.size()>0){
createTree(l) ;
}
//需要根据数据的fbdm和代码相比,如果b节点的fbdm等于a节点的dm,则将b节点add到a节点下
if(nodes[i]!=null&&i>0&&map.get("fbdm").equals("000")){
nodes[0].add(nodes[i]);
}
}
tree = new JTree(nodes[0]);
}
/*
* 传入一个节点,根据这个节点取它所有的子节点
*/
public ArrayList getsubtree(HashMap m){
ArrayList l = new ArrayList();
String dm = (String)m.get("dm");
for(int i=0;i<list.size();i++){
HashMap map = (HashMap) list.get(i);
String pdm = (String) map.get("fbdm");
if(pdm.equals(dm)){
System.out.println(map.get("mc"));
l.add(map);
}
}
return l;
}
class NodeSelectionListener extends MouseAdapter {
JTree tree;
NodeSelectionListener(JTree tree) {
this.tree = tree;
}
public void mouseClicked(MouseEvent e) {
//得到被选的节点
int x = e.getX();
int y = e.getY();
int row = tree.getRowForLocation(x, y);
TreePath path = tree.getPathForRow(row);
//判断是否单击了节点
if (path != null) {
//取得被单击的节点
CheckNode node = (CheckNode) path.getLastPathComponent();
System.out.println("row====="+node.getUserObject().toString());
boolean isSelected = !(node.isSelected());
//设置被单击的节点CheckBox,使其状态与原来状态相反
node.setSelected(isSelected);
//如果节点是被选中,则展开子节点
if (isSelected) {
tree.expandPath(path);
// tree.collapsePath(path);
}
//如果被选节点不是叶节点,将其所有子节点设置为CheckBox状态设成与其相同的状态
if(!node.isLeaf()){
node.getNextNode();
Enumeration enu= node.children();
while (enu.hasMoreElements()) {
CheckNode n = (CheckNode) enu.nextElement();
n.setSelected(node.isSelected());
if(!n.isLeaf()){
Enumeration enuc= n.children();
while (enuc.hasMoreElements()) {
CheckNode c = (CheckNode) enuc.nextElement();
c.setSelected(node.isSelected());
}
}
}
}
//刷新树
((DefaultTreeModel) tree.getModel()).nodeChanged(node);
tree.revalidate();
tree.repaint();
}
}
}
public static void main(String args[]) throws Exception {
ArrayList list = new ArrayList();
HashMap m = new HashMap();
m.put("mc","父");
m.put("dm","001");
m.put("fbdm","000");
m.put("bm","001001");
HashMap m2 = new HashMap();
m2.put("mc","孩子1");
m2.put("dm","001");
m2.put("fbdm","000");
m2.put("bm","001002");
HashMap m3 = new HashMap();
m3.put("mc","孩子2");
m3.put("dm","002");
m3.put("fbdm","000");
m3.put("bm","001003");
HashMap m4 = new HashMap();
m4.put("mc","孙子1");
m4.put("dm","003");
m4.put("fbdm","002");
m4.put("bm","001004");
HashMap m5 = new HashMap();
m5.put("mc","孙子2");
m5.put("dm","005");
m5.put("fbdm","002");
m5.put("bm","001005");
HashMap m6 = new HashMap();
m6.put("mc","曾孙");//问题就在这里它应该作为孙子2的子结点放在孙子2下面的,但没有放
m6.put("dm","006");
m6.put("fbdm","005");
m6.put("bm","001006");
list.add(m);
list.add(m2);
list.add(m3);
list.add(m4);
list.add(m5);
list.add(m6);
TreeExample frame = new TreeExample("树",list,true);
File file = new File("TreeExample.java");
System.out.println(" " + file.getCanonicalPath());
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(300, 200);
frame.setVisible(true);
}
}
class CheckRenderer extends JPanel implements TreeCellRenderer {
//树的节点JPanel编辑,每个节点都是一个JPanel,JPanel中有一个JCheckBox和一个JLabel
//TreeCellRenderer从DefaultMutableTreeNode(即CheckNode)中取得数据设置节点
//TreeCellRenderer主要设置Tree的外观,
protected JCheckBox check;
protected TreeLabel label;
public CheckRenderer() {
setLayout(null);
add(check = new JCheckBox());
add(label = new TreeLabel());
check.setBackground(UIManager.getColor("Tree.textBackground"));
label.setForeground(UIManager.getColor("Tree.textForeground"));
}
public Component getTreeCellRendererComponent(JTree tree, Object value,
boolean isSelected, boolean expanded, boolean leaf, int row,
boolean hasFocus) { DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;
Object userObj = treeNode.getUserObject(); if (userObj instanceof HashMap) {
label.setText(((HashMap)userObj).get("mc").toString());
}
String stringValue = tree.convertValueToText(value, isSelected,
expanded, leaf, row, hasFocus);
setEnabled(tree.isEnabled());
check.setSelected(((CheckNode) value).isSelected());
label.setFont(tree.getFont());
// label.setText(stringValue);
label.setSelected(isSelected);
label.setFocus(hasFocus);
if (leaf) {
if(((CheckNode) value).getIcon()!=null){
label.setIcon(((CheckNode) value).getIcon());
}else{
label.setIcon(UIManager.getIcon("Tree.leafIcon"));
}
} else if (expanded) {
label.setIcon(UIManager.getIcon("Tree.openIcon"));
} else {
label.setIcon(UIManager.getIcon("Tree.closedIcon"));
}
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));
}
//布局check和label
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 void setBackground(Color color) {
if (color instanceof ColorUIResource)
color = null;
super.setBackground(color);
} public class TreeLabel extends JLabel {
boolean isSelected;
boolean hasFocus;
public TreeLabel() {
}
public void setBackground(Color color) {
if (color instanceof ColorUIResource)
color = null;
super.setBackground(color);
} public void paint(Graphics g) {
String str;
if ((str = getText()) != null) {
if (0 < str.length()) {
if (isSelected) {
g.setColor(UIManager
.getColor("Tree.selectionBackground"));
} else {
g.setColor(UIManager.getColor("Tree.textBackground"));
}
Dimension d = getPreferredSize();
int imageOffset = 0;
Icon currentI = getIcon();
if (currentI != null) {
imageOffset = currentI.getIconWidth()
+ Math.max(0, getIconTextGap() - 1);
}
g.fillRect(imageOffset, 0, d.width - 1 - imageOffset,
d.height);
if (hasFocus) {
g.setColor(UIManager
.getColor("Tree.selectionBorderColor"));
g.drawRect(imageOffset, 0, d.width - 1 - imageOffset,
d.height - 1);
}
}
}
super.paint(g);
} public Dimension getPreferredSize() {
Dimension retDimension = super.getPreferredSize();
if (retDimension != null) {
retDimension = new Dimension(retDimension.width + 3,
retDimension.height);
}
return retDimension;
} public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
} public void setFocus(boolean hasFocus) {
this.hasFocus = hasFocus;
}
}
}//结点数据类
class CheckNode extends DefaultMutableTreeNode {
private int selectionMode = 0;
private boolean isSelected = false;
private Icon icon = null;
private String name;
static HashMap map;
public CheckNode() {
this(null);
} public CheckNode(Object userObject) {
this(userObject, true, false,map);
}
public CheckNode(Object userObject, boolean allowsChildren,
boolean isSelected,HashMap map) {
super(userObject, allowsChildren);
this.isSelected = isSelected;
this.map = map;
}
public void setName(String name) {
this.name = name;
}
public int getSelectionMode() {
return selectionMode;
} public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
} public boolean isSelected() {
return isSelected;
}
public void setIcon(Icon icon){
this.icon = icon;
}
public Icon getIcon(){
return icon;
}
public String getName(){
name = (String)map.get("mc");
return name;
}
}
private void addChild(CheckNode fatherNode,ArrayList l) {
HashMap map = null;
for (int i = 0; i < l.size(); i++) {
map = (HashMap) l.get(i);
CheckNode child = new CheckNode(map);
ArrayList ll = getsubtree(map);
fatherNode.add(child);
addChild(child,ll);
}
} public void createTree(ArrayList ll) {
HashMap map = null;
CheckNode top = null;
for (int i = 0; i < ll.size(); i++) {
map = (HashMap) ll.get(i);
if (map.get("fbdm").equals("000")) {
top = new CheckNode(map);
ArrayList l = getsubtree(map);
addChild(top,l);
} }
tree = new JTree(top);
}
另外,你的构造树的方法也不对,用下面的方式构造
ArrayList list = new ArrayList();
HashMap m = new HashMap();
m.put("mc", "fu");
m.put("dm", "001");
m.put("fbdm", "000");
m.put("bm", "001001");
HashMap m2 = new HashMap();
m2.put("mc", "haizi1");
m2.put("dm", "002");
m2.put("fbdm", "001");
m2.put("bm", "001002");
HashMap m3 = new HashMap();
m3.put("mc", "haizi2");
m3.put("dm", "003");
m3.put("fbdm", "001");
m3.put("bm", "001003");
HashMap m4 = new HashMap();
m4.put("mc", "sunzi1");
m4.put("dm", "004");
m4.put("fbdm", "003");
m4.put("bm", "001004");
HashMap m5 = new HashMap();
m5.put("mc", "sunzi2");
m5.put("dm", "005");
m5.put("fbdm", "003");
m5.put("bm", "001005");
HashMap m6 = new HashMap();
m6.put("mc", "zengsun");
m6.put("dm", "006");
m6.put("fbdm", "005");
m6.put("bm", "001006");
list.add(m);
list.add(m2);
list.add(m3);
list.add(m4);
list.add(m5);
list.add(m6);
感觉问题有两处,一处是测试用例(父亲的dm应该是'000',fbdm就不能是'000'了),
另一处就是你的递归,递归遍历树需要递归的时候建立
另外我写了个递归的函数,调用的时候需要这样:tree=new JTree( createTree(list,null,null));
/*
* 循环list生成树节点,问题就出在这里
*/
public CheckNode createTree(ArrayList ll,CheckNode root,HashMap map){
//递归入口
if (root==null) {
map=(HashMap)ll.get(0);
root=new CheckNode(map); }
//获得子节点集合
ArrayList l = getsubtree(map);
//循环子节点建立父子关系并且递归遍历
for(int j = 0;j <l.size();j++){
HashMap tempmap = (HashMap) l.get(j);
CheckNode tempnode = new CheckNode(tempmap);
if(tempnode!=null){
root.add(tempnode);
createTree(l,tempnode,tempmap) ;
}
}
return root;
}