引自:http://blog.youkuaiyun.com/jimmy292/archive/2010/03/03/5341192.aspx
1.1 创建树组件
1.1.1 最简方式 :
在显示时,树组件会带上JTree默认的节点。
1.1.2 指定树的节点后创建树:
root.add( new DefaultMutableTreeNode( " 子节点 " ));
JTree tree = new JTree(root);
1.1.3 将树加入到面板中
以下是将树加上滚动窗格后加入一个面板的示例程序。
panel.setLayout( new GridLayout( 1 , 1 ));
panel.add( new JScrollPane(tree));
1.2 树节点相关
1.2.1 取得树的根节点
DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
1.2.2 更新树的根节点

DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
model.setRoot(newRoot);
model.reload();
tree.updateUI();
1.2.3 从一个节点开始递归遍历其下的所有节点
Category category = (Category)node.getUserObject();
StringBuilder sb = new StringBuilder(category.getText());
if (node.getChildCount() >= 0 ) {
for (Enumeration <?> e = node.children(); e.hasMoreElements(); ) {
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)e.nextElement();
sb.append(getNodeText(childNode));
}
}
return sb.toString();
}
1.2.4 在某节点下创建一个节点
childNode.setUserObject(

parentNode.add(childNode);
1.2.5 节点改名
selectedCategory.setName( "

clickedNode.setUserObject(selectedCategory);
1.2.6 删除节点
model.removeNodeFromParent(clickedNode);
注意被删除的节点必须有父节点,若要删除根节点直接用null去替代原有根节点即可,
1.2.7 遍历用户选择的树节点
for (TreePath selPath:paths){
Object[] nodes = selPath.getPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes[nodes.length - 1 ];
// 对node进行处理
}
1.3 树的事件处理
1.3.1 左键点击事件处理
public void mousePressed(MouseEvent e) {
int selRow = tree.getRowForLocation(e.getX(), e.getY()); // 返回节点所在的行,-1表示鼠标定位不在显示的单元边界内
TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); // 返回指定节点的树路径
boolean condition = true ;
condition = condition && (selRow != - 1 ); // 如果选中
// condition = condition && (e.getButton() == 1); // 左键 e.getButton() == 1 右键 e.getButton() == 3
condition = condition && (e.getClickCount() == 1 ); // 单击
// 如果是左键点击
if (condition == true && (e.getButton() == 1 )) {
Object[] nodes = selPath.getPath();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes[nodes.length - 1 ];
Category selectedCategory = (Category)node.getUserObject();


}
}
});
1.3.2 在树节点上点击右键弹出右键菜单
public void mousePressed(MouseEvent e) {
int selRow = tree.getRowForLocation(e.getX(), e.getY()); // 返回节点所在的行,-1表示鼠标定位不在显示的单元边界内
TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); // 返回指定节点的树路径
boolean condition = true ;
condition = condition && (selRow != - 1 ); // 如果选中
condition = condition && (e.getClickCount() == 1 ); // 单击
// 如果是右键点击
if (condition == true && (e.getButton() == 3 )){
Object[] nodes = selPath.getPath();
DefaultMutableTreeNode rightClickedNode = (DefaultMutableTreeNode) nodes[nodes.length - 1 ];


popupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
});
1.4 树的渲染
1.4.1 树节点渲染器示例
private static final long serialVersionUID = 8532405600839140757L ;
private static final ImageIcon categoryLeafIcon = new ImageIcon(CategoryNodeRenderer. class .getResource( " /categoryLeaf.gif " ));
private static final ImageIcon openFolderIcon = new ImageIcon(CategoryNodeRenderer. class .getResource( " /openFolder.gif " ));
private static final ImageIcon closedFolderIcon = new ImageIcon(CategoryNodeRenderer. class .getResource( " /closedFolder.gif " ));
public Component getTreeCellRendererComponent(JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus){
super .getTreeCellRendererComponent(tree,
value,
sel,
expanded,
leaf,
row,
hasFocus);
if (leaf){
setIcon(categoryLeafIcon);
}
else if (expanded){
setIcon(openFolderIcon);
}
else {
setIcon(closedFolderIcon);
}
return this ;
}
}
1.4.2 用树节点渲染器渲染一棵树
JTree tree = new JTree(root);
tree.setCellRenderer( new CategoryNodeRenderer());
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
一个目录缓存设计的进化过程:
任务:数据库中有六千余条目录(id,pid,name)数据组成一棵目录树,需要通过WebService服务提供给客户端显示出来(Swing中的JTree)。
实现功能的第一步:在客户端的树显示时通过网络得到顶层目录,再根据用户的点击逐级展开下级目录。此方案优点:实现简单;缺点:点击多次容易使人厌烦,速度不行。
客户端实现改善的第二步:启动一个线程从服务器加载数据逐渐生成一个节点树,再交给界面上的JTree命其更新。此举对操作友好型有改进,速度上也有所提高。
客户端实现改善的第三步:先起线程从服务器端一次性下载完全部数据,而后置入内存,再以此为基础构建树。此举对速度也有明显提高。
客户端实现改善的第四步:将已经加载的节点从内存中删除,使查找时间逐渐减小。此举对速度有一定提高。
服务器端实现改善的第四步:不使用Hibernate的对象映射而单独遴选字段组建成一个包装类,此举对速度有一定提高。
服务器端实现改善的第五步:直接采用优化的存储过程将表中必要行集的数据在数据库段形成大文本,一次性传出,WS服务器端只负责传输,此举对速度有明显提高。
通过以上措施,完成包括六千个节点的树显示速度数量级的提高,综合评价一下,以上逐步中,第三步:在客户端另起线程从内存加载数据形成一棵完整的节点树再通知界面更新 和 第五步:通过存储过程直接取得行集合并结果对提高速度帮助最大。