++ 树(Tree)的使用与介绍
10-1:使用 JTree 组件:
java.lang.Object
--java.awt.Component
--java.awt.Container
--javax.swing.JComponent
--javax.swing.JTree
JTree 构造函数:
JTree():建立一棵系统默认的树。
JTree(Hashtable value):利用 Hashtable 建立树,不显示 root node(根节点).
JTree(Object[] value):利用 Object Array 建立树,不显示 root node.
JTree(TreeModel newModel):利用 TreeModel 建立树。
JTree(TreeNode root):利用 TreeNode 建立树。
JTree(TreeNode root,boolean asksAllowsChildren):利用 TreeNode 建立树,并决定是否允许子
节点的存在.
JTree(Vector value):利用 Vector 建立树,不显示 root node.
范例:
InitalTree.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class InitalTree{
public InitalTree(){
JFrame f=new JFrame("TreeDemo");
Container contentPane=f.getContentPane();
JTree tree=new JTree();
JScrollPane scrollPane=new JScrollPane();
scrollPane.setViewportView(tree);
contentPane.add(scrollPane);
f.pack();
f.setVisible(true);
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
}
public static void main(String[] args){
new InitalTree();
}
}
10-2:以 Hashtable 构造 JTree:
上面的例子对我们并没有裨的帮助,因为各个节点的数据均是 java 的默认值,而非我们
自己设置的。因此我们需利用其他 JTree
构造函数来输入我们想要的节点数据。以下范例我们以 Hashtable 当作 JTree 的数据输入:
范例:TreeDemo1.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class TreeDemo1{
public TreeDemo1(){
JFrame f=new JFrame("TreeDemo1");
Container contentPane=f.getContentPane();
String[] s1={"公司文件","个人信件","私人文件"};
String[] s2={"本机磁盘(C:)","本机磁盘(D:)","本机磁盘(E:)"};
String[] s3={"奇摩站","职棒消息","网络书店"};
Hashtable hashtable1=new Hashtable();
Hashtable hashtable2=new Hashtable();
hashtable1.put("我的公文包",s1);
hashtable1.put("我的电脑",s2);
hashtable1.put("收藏夹",hashtable2);
hashtable2.put("网站列表",s3);
Font font = new Font("Dialog", Font.PLAIN, 12);
Enumeration keys = UIManager.getLookAndFeelDefaults().keys();
/**定义 widnows 界面**/
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
if (UIManager.get(key) instanceof Font) {
UIManager.put(key, font);
}
}
try{
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}catch(Exception el){
System.exit(0);
}
/**定义 widnows 界面**/
JTree tree=new JTree(hashtable1);
JScrollPane scrollPane=new JScrollPane();
scrollPane.setViewportView(tree);
contentPane.add(scrollPane);
f.pack();
f.setVisible(true);
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
}
public static void main(String[] args){
new TreeDemo1();
}
}
纯 XP 界面的设置:
10-3:以 TreeNode 构造 JTree:
JTree 上的每一个节点就代表一个 TreeNode 对象,TreeNode 本身是一个 Interface,里面定
义了 7 个有关节点的方法,例如判断是否
为树叶节点、有几个子节点(getChildCount())、父节点为何(getparent())等等、这些方法的定
义你可以在 javax.swing.tree 的
package 中找到,读者可自行查阅 java api 文件。在实际的应用上,一般我们不会直接实作
此界面,而是采用 java 所提供的
DefaultMutableTreeMode 类,此类是实作 MutableTreeNode 界面而来,并提供了其他许多实
用的方法。MutableTreeNode 本身也是一
个 Interface,且继承了 TreeNode 界面此类主要是定义一些节点的处理方式,例如新增节点
(insert())、删除节点(remove())、设置
节点(setUserObject())等。整个关系如下图:
TreeNode----extends--->MutableTreeNode---implements---DefaultMutableTreeNode
接 下 来 我 们 来 看 如 何 利 DefaultMutableTreeNode 来 建 立 JTree, 我 们 先 来 看
DefaultMutableTreeNode 的构造函数:
DefaultMutableTreeNode 构造函数:
DefaultMutableTreeNode():建立空的 DefaultMutableTreeNode 对象。
DefaultMutableTreeNode(Object userObject): 建 立 DefaultMutableTreeNode 对 象 , 节 点 为
userObject 对象。
DefaultMutableTreeNode(Object
userObject,Boolean
allowsChildren):
建
立
DefaultMutableTreeNode 对象,节点为 userObject 对
以下为利用 DefaultMutableTreeNode 建立 JTree 的范例:TreeDemo2.java
此程序"资源管理器"为此棵树的根节点.
象并决定此节点是否允许具有子节点。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
public class TreeDemo2{
public TreeDemo2(){
JFrame f=new JFrame("TreeDemo2");
Container contentPane=f.getContentPane();
DefaultMutableTreeNode root=new DefaultMutableTreeNode("资源管理器");
DefaultMutableTreeNode node1=new DefaultMutableTreeNode("我的公文包");
DefaultMutableTreeNode node2=new DefaultMutableTreeNode("我的电脑");
DefaultMutableTreeNode node3=new DefaultMutableTreeNode("收藏夹");
DefaultMutableTreeNode node4=new DefaultMutableTreeNode("Readme");
root.add(node1);
root.add(node2);
root.add(node3);
root.add(node4);
DefaultMutableTreeNode leafnode=new DefaultMutableTreeNode("公司文件");
node1.add(leafnode);
leafnode=new DefaultMutableTreeNode("私人文件");
node1.add(leafnode);
leafnode=new DefaultMutableTreeNode("个人信件");
leafnode=new DefaultMutableTreeNode("本机磁盘(C:)");
node2.add(leafnode);
leafnode=new DefaultMutableTreeNode("本机磁盘(D:)");
node2.add(leafnode);
leafnode=new DefaultMutableTreeNode("本机磁盘(E:)");
node2.add(leafnode);
DefaultMutableTreeNode node31=new DefaultMutableTreeNode("网站列表");
node3.add(node31);
leafnode=new DefaultMutableTreeNode("奇摩站");
node31.add(leafnode);
leafnode=new DefaultMutableTreeNode("职棒消息");
node31.add(leafnode);
leafnode=new DefaultMutableTreeNode("网络书店");
node31.add(leafnode);
JTree tree=new JTree(root);
JScrollPane scrollPane=new JScrollPane();
scrollPane.setViewportView(tree);
contentPane.add(scrollPane);
f.pack();
f.setVisible(true);
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
}
public static void main(String[] args){
new TreeDemo2();
}
}
10-4:以 TreeModel 构造 JTree.
除了以节点的观念(TreeNode)建立树之外,你可以用 data model 的模式建立树。树的 data
addTreeModelListener(TreeModelListener l): 增加一个 TreeModelListener 来监控
model 称为 TreeModel,用此模式的好处
是可以触发相关的树事件,来处理树可能产生的一些变动。TreeModel 是一个 interface,里面
定义了 8 种方法;如果你是一个喜欢自己
动手做的人,或是你想显示的数据格式很复杂,你可以考虑直接实作 TreeModel 界面中所定
义的方法来构造出 JTree.TreeModel 界面
的方法如下所示:
TreeModel 方法:
void
TreeModelEvent 事件。
Object
int
int
Object
boolean
void
void
何应对。
getChild(Object parent,int index):返回子节点。
getChildCount(Object parent):返回子节点数量.
getIndexOfChild(Object parent,Object child):返回子节点的索引值。
getRoot():返回根节点。
isLeaf(Object node):判断是否为树叶节点。
removeTreeModelListener(TreeModelListener l):删除 TreeModelListener。
valueForPathChanged(TreePath path,Object newValue):当用户改变 Tree 上的值时如
你可以实作出这 8 种方法,然后构造出自己想要的 JTree,不过在大部份的情况下我们通
常不会这样做,毕竟要实作出这 8 种方法不
是件很轻松的事,而且 java 本身也提供了一个默认模式,叫做 DefaultTreeModel,这个类已
经实作了 TreeModel 界面,也另外提供许
多实用的方法。利用这个默认模式,我们便能很方便的构造出 JTree 出来了。下面为
DefaultTreeModel 的构造函数与范例:
DefaultTreeModel 构造函数:
DefaultTreeModel(TreeNode root):建立 DefaultTreeModel 对象,并定出根节点。
DefaultTreeModel(TreeNode root,Boolean asksAllowsChildren): 建 立 具 有 根 节 点 的
DefaultTreeModel 对象,并决定此节点是否允
许具有子节点。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import com.incors.plaf.alloy.*;//组件的下载网址 http://www.incors.com/lookandfeel/
/*将 alloy.jar 放在 c:\j2sdk1.4.0\jre\lib\ext\目录下.
*/
public class TreeDemo3
{
public TreeDemo3()
{
JFrame f = new JFrame("TreeDemo");
Container contentPane = f.getContentPane();
DefaultMutableTreeNode root = new DefaultMutableTreeNode("资源管理器");
DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("我的公文包");
DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("我的电脑");
DefaultMutableTreeNode node3 = new DefaultMutableTreeNode("收藏夹");
DefaultMutableTreeNode node4 = new DefaultMutableTreeNode("Readme");
DefaultTreeModel treeModel = new DefaultTreeModel(root);
/*DefaultTreeModel 类所提供的 insertNodeInto()方法加入节点到父节点的数量.
*利用 DefaultMutableTreeNode 类所提供的 getChildCount()方法取得目前子节点的
数量.
*/
treeModel.insertNodeInto(node1, root, root.getChildCount());
treeModel.insertNodeInto(node2, root, root.getChildCount());
treeModel.insertNodeInto(node3, root, root.getChildCount());
treeModel.insertNodeInto(node4, root, root.getChildCount());
DefaultMutableTreeNode leafnode = new
DefaultMutableTreeNode("公司文件");
//DefaultTreeModel 类所提供的 insertNodeInto()方法加入节点到父节点的数量.
treeModel.insertNodeInto(leafnode, node1, node1.getChildCount());
leafnode = new DefaultMutableTreeNode("个人信件");
treeModel.insertNodeInto(leafnode, node1, node1.getChildCount());
leafnode = new DefaultMutableTreeNode("私人文件");
treeModel.insertNodeInto(leafnode, node1, node1.getChildCount());
leafnode = new DefaultMutableTreeNode("本机磁盘(C:)");
treeModel.insertNodeInto(leafnode, node2, node2.getChildCount());
leafnode = new DefaultMutableTreeNode("本机磁盘(D:)");
treeModel.insertNodeInto(leafnode, node2, node2.getChildCount());
leafnode = new DefaultMutableTreeNode("本机磁盘(E:)");
treeModel.insertNodeInto(leafnode, node2, node2.getChildCount());
DefaultMutableTreeNode node31 = new DefaultMutableTreeNode("网站列表");
treeModel.insertNodeInto(node31, node3, node3.getChildCount());
leafnode = new DefaultMutableTreeNode("奇摩站");
treeModel.insertNodeInto(leafnode, node3, node3.getChildCount());
leafnode = new DefaultMutableTreeNode("职棒消息");
treeModel.insertNodeInto(leafnode, node3, node3.getChildCount());
leafnode = new DefaultMutableTreeNode("网络书店");
treeModel.insertNodeInto(leafnode, node3, node3.getChildCount());
try {
LookAndFeel alloyLnF = new AlloyLookAndFeel();
UIManager.setLookAndFeel(alloyLnF);
} catch (UnsupportedLookAndFeelException ex) {
// You may handle the exception here
}
// this line needs to be implemented in order to make JWS work properly
UIManager.getLookAndFeelDefaults().put("ClassLoader",
getClass().getClassLoader());
//以 TreeModel 建立 JTree。
JTree tree = new JTree(treeModel);
/*改变 JTree 的外观**/
tree.putClientProperty("JTree.lineStyle","Horizontal");
/*改变 JTree 的外观**/
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(tree);
contentPane.add(scrollPane);
f.pack();
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public static void main(String args[]) {
new TreeDemo3();
}
}
10-5:改变 JTree 的外观:
你可以使用 JComponent 所提供的 putClientProperty(Object key,Object value)方法来设置 java
默认的 JTree 外观,设置方式共有
3 种:
1.tree.putClientProperty("JTree.lineStyle","None"):java 默认值。
2.tree.putClientProperty("JTree.lineStyle","Horizontal"):使 JTree 的文件夹间具有水平分隔线。
3.tree.putClientProperty("JTree.lineStyle","Angled"):使 JTree 具有类似 Windows 文件管理器的
直角连接线。
具体怎样做,可看上例.
10-6:更换 JTree 节点图案:
JTree 利用 TreeCellRenderer 界面来运行绘制节点的工作,同样的,你不需要直接支实作
这个界面所定义的方法,因为 java 本身提
供 一 个 已 经 实 作 好 的 类 来 给 我 们 使 用 , 此 类 就 是 DefaultTreeCellRenderer, 你 可 以 在
javax.swing.tree package 中找到此类所提供
的方法。下面为使用 DefaultTreeCellRenderer 更改节点图案的一个例子:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import com.incors.plaf.alloy.*;
public class TreeDemo4{
public TreeDemo4(){
JFrame f=new JFrame("TreeDemo");
Container contentPane=f.getContentPane();
DefaultMutableTreeNode root = new DefaultMutableTreeNode("资源管理器");
DefaultMutableTreeNode node1 = new DefaultMutableTreeNode("我的公文包");
DefaultMutableTreeNode node2 = new DefaultMutableTreeNode("我的电脑");
DefaultMutableTreeNode node3 = new DefaultMutableTreeNode("收藏夹");