對于JTree比較重要的幾個類或接口:
1。TreeMode是一個接口,是構(gòu)建樹的模型,接口中比較重要的幾個函數(shù)是:getChild、getChildCount、getRoot、getIndexOfChild、isLeaf。如果想把一些特殊的東西抽象成一棵樹,那么就可以實現(xiàn)該接口,用自己構(gòu)造的這個模型來創(chuàng)建樹JTree(TreeModel newModel)
2。TreeNode是一個接口,代表樹的節(jié)點。DefaultMutableTreeNode是該接口的一個實現(xiàn),可以直接用來創(chuàng)建樹的節(jié)點。
3。TreePath是一個類,負責節(jié)點到根的路徑
4。TreeSelectionModel是一個接口,表示樹選擇組件的當前狀態(tài)。DefaultTreeSelectionModel類是該接口的一個實現(xiàn)類。
構(gòu)造方法摘要 |
JTree()
返回帶有示例模型的 JTree 。 |
JTree(Hashtable<?,?> value)
返回從 Hashtable 創(chuàng)建的 JTree ,它不顯示根。 |
JTree(Object[] value)
返回 JTree ,指定數(shù)組的每個元素作為不被顯示的新根節(jié)點的子節(jié)點。 |
JTree(TreeModel newModel)
返回 JTree 的一個實例,它顯示根節(jié)點 - 使用指定的數(shù)據(jù)模型創(chuàng)建樹。 |
JTree(TreeNode root)
返回 JTree ,指定的 TreeNode 作為其根,它顯示根節(jié)點。 |
JTree(TreeNode root, boolean asksAllowsChildren)
返回 JTree ,指定的 TreeNode 作為其根,它用指定的方式顯示根節(jié)點,并確定節(jié)點是否為葉節(jié)點。 |
JTree(Vector<?> value)
返回 JTree ,指定 Vector 的每個元素作為不被顯示的新根節(jié)點的子節(jié)點。 |
常用方法:
1。得到模型:
getModel()或(DefaultTreeModel)getModel()
2。得到根:
getModel().getRoot()或(DefaultMutableTreeNode)getModel().getRoot()
3。根據(jù)node得到path:
TreePath visiblePath = new TreePath(((DefaultTreeModel)getModel()).getPathToRoot(node))
4。根據(jù)Path展開到該節(jié)點:
makeVisible(visiblePath)
5。根據(jù)path設定該節(jié)點選定
tree.setSelectionPath(visiblePath)
6。滾動到可見位置:
scrollRowToVisible(int row)
7。展開樹<從根展開或從某一個節(jié)點展開>
關于JTree的展開
// If expand is true, expands all nodes in the tree.
// Otherwise, collapses all nodes in the tree.
public static void expandAll(JTree tree, boolean expand) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
// Traverse tree from root
expandAll(tree, new TreePath(root), expand);
}
private static void expandAll(JTree tree, TreePath parent, boolean expand) {
// Traverse children
TreeNode node = (TreeNode) parent.getLastPathComponent();
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
expandAll(tree, path, expand);
}
}
// Expansion or collapse must be done bottom-up
if (expand) {
tree.expandPath(parent);
} else {
tree.collapsePath(parent);
}
}
8。遍歷樹的所有節(jié)點<從根遍歷或從某一個節(jié)點遍歷>
public static void visitAllNodes(JTree tree) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
visitAllNodes(tree,root);
}
public static void visitAllNodes(JTree tree,TreeNode node) {
// node is visited exactly once
//you can do your things about this node,such as:
tree.makeVisible(new TreePath(
((DefaultTreeModel)tree.getModel()).getPathToRoot(node)));
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
visitAllNodes(tree,n);
}
}
}
9。遍歷樹已經(jīng)展開的節(jié)點<從根遍歷或從某一個節(jié)點遍歷>
// Traverse all expanded nodes in tree
public static void visitAllExpandedNodes(JTree tree) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
visitAllExpandedNodes(tree, new TreePath(root));
}
public static void visitAllExpandedNodes(JTree tree, TreePath parent) {
// Return if node is not expanded
if (!tree.isVisible(parent)) {
return;
}
// node is visible and is visited exactly once
TreeNode node = (TreeNode) parent.getLastPathComponent();
//you can do your things about this node,such as:
System.out.println(node.toString());
// Visit all children
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
visitAllExpandedNodes(tree, path);
}
}
}
一個較為完整的練習:
import java.awt.Dimension;
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Enumeration;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.BoxLayout;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class JTreeDemo {
public static void expandAll(JTree tree, boolean expand) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
// Traverse tree from root
expandAll(tree, new TreePath(root), expand);
}
private static void expandAll(JTree tree, TreePath parent, boolean expand) {
// Traverse children
TreeNode node = (TreeNode) parent.getLastPathComponent();
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
expandAll(tree, path, expand);
}
}
// Expansion or collapse must be done bottom-up
if (expand) {
tree.expandPath(parent);
} else {
tree.collapsePath(parent);
}
}
public static void visitAllNodes(JTree tree) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
visitAllNodes(tree,root);
}
public static void visitAllNodes(JTree tree,TreeNode node) {
// node is visited exactly once
//you can do your things about this node,such as:
tree.makeVisible(new TreePath(
((DefaultTreeModel)tree.getModel()).getPathToRoot(node)));
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
visitAllNodes(tree,n);
}
}
}
// Traverse all expanded nodes in tree
public static void visitAllExpandedNodes(JTree tree) {
TreeNode root = (TreeNode) tree.getModel().getRoot();
visitAllExpandedNodes(tree, new TreePath(root));
}
public static void visitAllExpandedNodes(JTree tree, TreePath parent) {
// Return if node is not expanded
if (!tree.isVisible(parent)) {
return;
}
// node is visible and is visited exactly once
TreeNode node = (TreeNode) parent.getLastPathComponent();
//you can do your things about this node,such as:
System.out.println(node.toString());
// Visit all children
if (node.getChildCount() >= 0) {
for (Enumeration e = node.children(); e.hasMoreElements();) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
visitAllExpandedNodes(tree, path);
}
}
}
public static JTree tr;
public static void main(String[] args) {
// 構(gòu)造函數(shù):JTree()
JTree example1 = new JTree();
tr=example1;
example1.setBackground(Color.lightGray);
example1.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent me){
try{
visitAllNodes(tr);
Thread.sleep(2000);
System.out.println(tr.getPathForRow(1).toString());
expandAll(tr,tr.getPathForRow(1),false);
Thread.sleep(2000);
visitAllExpandedNodes(tr);
}catch(InterruptedException e){
e.printStackTrace();
}
}
});
// 構(gòu)造函數(shù):JTree(Object[] value)
Object[] letters = { " a ", " b ", " c ", " d ", " e " };
JTree example2 = new JTree(letters);
// 構(gòu)造函數(shù):JTree(TreeNode root)(TreeNode空)
// 用空結(jié)點創(chuàng)建樹
DefaultMutableTreeNode node1 = new DefaultMutableTreeNode(); // 定義樹結(jié)點
JTree example3 = new JTree(node1); // 用此樹結(jié)點做參數(shù)調(diào)用 JTree的構(gòu)造函數(shù)創(chuàng)建含有一個根結(jié)點的樹
// 構(gòu)造函數(shù):JTree(TreeNode root)(同上,只是TreeNode非空)
// 用一個根結(jié)點創(chuàng)建樹
DefaultMutableTreeNode node2 = new DefaultMutableTreeNode(" Color ");
JTree example4 = new JTree(node2); // 結(jié)點不可以顏色,默認為白面黑字
example4.setBackground(Color.lightGray);
// 構(gòu)造函數(shù):JTree(TreeNode root, boolean
// asksAllowsChildren)(同上,只是TreeNode又有不同)
// 使用DefaultMutableTreeNode類先用一個根結(jié)點創(chuàng)建樹,設置為可添加孩子結(jié)點,再添加孩子結(jié)點
DefaultMutableTreeNode color = new DefaultMutableTreeNode(" Color ",
true);
DefaultMutableTreeNode gray = new DefaultMutableTreeNode(" Gray ");
color.add(gray);
color.add(new DefaultMutableTreeNode(" Red "));
gray.add(new DefaultMutableTreeNode(" Lightgray "));
gray.add(new DefaultMutableTreeNode(" Darkgray "));
color.add(new DefaultMutableTreeNode(" Green "));
JTree example5 = new JTree(color);
// 構(gòu)造函數(shù):JTree(TreeNode root)(同上,只是TreeNode非空)
// 通過逐個添加結(jié)點創(chuàng)建樹
DefaultMutableTreeNode biology = new DefaultMutableTreeNode(" Biology ");
DefaultMutableTreeNode animal = new DefaultMutableTreeNode(" Animal ");
DefaultMutableTreeNode mammal = new DefaultMutableTreeNode(" Mammal ");
DefaultMutableTreeNode horse = new DefaultMutableTreeNode(" Horse ");
mammal.add(horse);
animal.add(mammal);
biology.add(animal);
JTree example6 = new JTree(biology);
horse.isLeaf();
horse.isRoot();
// 構(gòu)造函數(shù):JTree(TreeModel newModel)
// 用DefaultMutableTreeNodel類定義一個結(jié)點再用這個結(jié)點做參數(shù)定義一個用DefaultTreeMode
// 創(chuàng)建一個樹的模型,再用JTree的構(gòu)造函數(shù)創(chuàng)建一個樹
DefaultMutableTreeNode root = new DefaultMutableTreeNode(" Root1 ");
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode(" Child1 ");
DefaultMutableTreeNode child11 = new DefaultMutableTreeNode(" Child11 ");
DefaultMutableTreeNode child111 = new DefaultMutableTreeNode(
" Child111 ");
root.add(child1);
child1.add(child11);
child11.add(child111);
DefaultTreeModel model = new DefaultTreeModel(root);
JTree example7 = new JTree(model);
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.setPreferredSize(new Dimension(700, 400));
panel.add(new JScrollPane(example1)); // JTree必須放在JScrollPane上
panel.add(new JScrollPane(example2));
panel.add(new JScrollPane(example3));
panel.add(new JScrollPane(example4));
panel.add(new JScrollPane(example5));
panel.add(new JScrollPane(example6));
panel.add(new JScrollPane(example7));
JFrame frame = new JFrame(" JTreeDemo ");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
}
另外一個例子,在該例子中筆者使用基于本機目錄構(gòu)建的模型來構(gòu)建樹:
/**
* 查API時發(fā)現(xiàn)1.4FileSystemView這個東東多了一些功能,
* 無聊地寫了這個文件目錄樹
*
* 聲明:使用j2sdk1.4
* 建議:實現(xiàn)自己的File類,以過濾掉一般文件,只剩下目錄
* 缺點:gui慢得要死,swing的通病?(my pc==256ddr,thunderbird900,xp)
*/
import java.awt.Component;
import java.io.*;
import javax.swing.*;
import javax.swing.event.TreeModelListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.*;
public class Test {
/**
* javax.swing.filechooser.FileSystemView在這個程序里很重要,
* 用法參考j2sdk1.4 API文檔
* 切記,1.4 not 1.3!!!!!!!!
*/
private static FileSystemView fileView;
int a=BB;
static int BB=34;
/**
*在這里使用了Singleton模式
* 不過似乎沒什么破用
*/
static FileSystemView getFileView() {
if (fileView == null)
fileView = FileSystemView.getFileSystemView();
return fileView;
}
public static void main(String[] args) throws Exception {
//如果加入下面這句,會亂碼.i wonder why
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
//initial frame
JFrame frame = new JFrame();
frame.setSize(400, 300);
//關閉窗口時退出程序
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//initial tree with customer TreeModel
JTree tree = new JTree(new CustomTreeModel());
//set customer TreeCellRenderer
tree.setCellRenderer(new CustomTreeCellRenderer());
frame.getContentPane().add(new JScrollPane(tree));
frame.setVisible(true);
}
}
class CustomTreeModel implements TreeModel {
private FileSystemView fileView;
public CustomTreeModel() {
fileView = Test.getFileView();
}
//返回根節(jié)點
public Object getRoot() {
return fileView.getRoots()[0];
}
//返回父節(jié)點parent的第index個子節(jié)點,index以0開始
public Object getChild(Object _parent, int index) {
File parent = (File) _parent;
return parent.listFiles()[index];
}
//返回父節(jié)點parent下,子節(jié)點child的位置,與上面的方法正好相反
public int getIndexOfChild(Object parent, Object child) {
File[] files = ((File) parent).listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].equals(child))
return i;
}
return -1;
}
//返回父節(jié)點parent的子節(jié)點數(shù)
public int getChildCount(Object parent) {
File[] files = ((File) parent).listFiles();
/**
*maybe driver not ready,ie cdrom
*then files is null
*/
if (files == null)
return -1;
return files.length;
}
//是否葉節(jié)點
public boolean isLeaf(Object node) {
return ((File) node).isFile();
}
public void valueForPathChanged(TreePath path, Object newValue) {
}
/**
*下面的方法要實現(xiàn),則要涉及比較復雜的事件處理
*如果有興趣,
*可以簡單的使用javax.swing.EventListenerList來實現(xiàn)
*/
public void addTreeModelListener(TreeModelListener l) {
}
public void removeTreeModelListener(TreeModelListener l) {
}
}
/**
* 如果沒有安裝自己的CellRenderer
* JTree默認的CellRenderer就是JLabel
* 它只是簡單的setText(node.toString)
* CustomeTreeCellRenderer也只是簡單取回
* windows默認的文件圖標和文件名,裝到JLabel上去
*/
class CustomTreeCellRenderer extends DefaultTreeCellRenderer {
/**
*
*/
private static final long serialVersionUID = 3892593039200536416L;
private FileSystemView fileView;
public CustomTreeCellRenderer() {
fileView = Test.getFileView();
}
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);
File file = (File) value;
setIcon(fileView.getSystemIcon(file));
setText(fileView.getSystemDisplayName(file));
return this;
}
}