您的位置:首页 > 编程语言 > Java开发

翻译:java中怎样使用树结构(How to Use Trees)(二)

2005-11-30 15:09 701 查看
个性化树显示
[/b]
 如前所述,树的每一个节点通常有一个图标和一些文字.你可以定制这些图标和文字.
 一个tree通常会展示一些特殊外观来显示节点间的联系.你可以通过简单的几步来自定义这些外观样式.首先,你可以用tree.setRootVisible(true)来显示根节点,用tree.setRootVisible(false)来隐藏根节点.然后,通过调用tree.setShowsRootHandles(true),可以让tree的顶级节点—根节点(如果可见)或者其子节点—展开或者收缩.最后,如果你采用java风格样式,你还可以自定义是否显示线条来展示树节点间的关系.
 默认的,java风格会在节点间画出一个带直角的直线.通过设置Tree.lineStyle属性,你可以指定不同的样式.例如,如果采用java风格,通过调用如下代码,可以用横线来组织各节点.
tree.putClientProperty("JTree.lineStyle", "Horizontal");
如果不想显示任何线条,则可以用如下代码:
tree.putClientProperty("JTree.lineStyle", "None");
不管风格如何,节点的默认图标由以下条件决定:节点是否是叶子
节点(leaf node),节点是否展开.例如:在windows风格下,叶子节点
的默认图标是一个点;在java风格下,叶子节点的默认图标却是一个纸
张图标.在我们展示的所有风格样式中,分支节点的默认图标是一个文
件夹图标.在展开或者收缩分支节点时,有些节点图标也有可能显示略
有不同.
我们可以非常容易的改变默认的图标.首先,增加一个[code]DefaultTreeCellRenderer
[/code]
的实例;然后,调用一下方法来指定你要采用的图标:
[code]setLeafIcon
(设置叶子节点),
setOpenIcon
(设置展开的分支节点), [/code]
[code]setClosedIcon
(设置收缩的分支节点).如果你不想让任何节点有图标,[/code]
只需设置每个图标为null就可以了.一旦设置好图标,就可以用tree的
setCellRenderer方法来指定[code]DefaultTreeCellRenderer渲染节点.
[/code]
[code]下面是一个例子,选自TreeIconDemo.java(后附其源代码)
[/code]
ImageIcon leafIcon = createImageIcon("images/middle.gif");
if (leafIcon != null) {
DefaultTreeCellRenderer renderer =
new DefaultTreeCellRenderer();
renderer.setLeafIcon(leafIcon);
tree.setCellRenderer(renderer);
}
如果你想更好的控制节点图标或者你想提供一个提示信息,那么你
[code]需要增加一个DefaultTreeCellRenderer的子类并且重载
[/code]
[code]getTreeCellRendererComponen方法.因为DefaultTreeCellRenderer
[/code]
[code]是JLabel的子类,所以你可以用JLabel的所有方法---比如setIcon----来
[/code]
[code]个性化DefaultTreeCellRenderer
.[/code]
[code] 下面的代码,来自
TreeIconDemo2.java
,,增加一个cellrenderer,通[/code]
过判断节点文字中是否包含”tutorial”来改变叶子节点图标.renderer也
可以改变提示文字,用粗体显示.
//...where the tree is initialized:
//Enable tool tips.
ToolTipManager.sharedInstance().registerComponent(tree);
ImageIcon tutorialIcon = createImageIcon("images/middle.gif");
if (tutorialIcon != null) {
tree.setCellRenderer(new MyRenderer(tutorialIcon));
}
...
class MyRenderer extends DefaultTreeCellRenderer {
Icon tutorialIcon;
 
public MyRenderer(Icon icon) {
tutorialIcon = icon;
}
 
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 && isTutorialBook(value)) {
setIcon(tutorialIcon);
setToolTipText("This book is in the Tutorial series.");
} else {
setToolTipText(null); //no tool tip
} 
 
return this;
}
 
protected boolean isTutorialBook(Object value) {
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)value;
BookInfo nodeInfo =
(BookInfo)(node.getUserObject());
String title = nodeInfo.bookName;
if (title.indexOf("Tutorial") >= 0) {
return true;
}
 
return false;
}
}
[code]你也许会奇怪:
cell renderer是如何工作的.当一个tree绘出每一[/code]
个节点时,既不是JTree,也不是风格样式包含执行绘制节点的代码.
相反,tree是通过调用cellrenderer的绘制代码来完成节点的绘制的.
例如:为了绘制一个含有字符串"The Java Programming Language"的
节点,tree会让它的cellrenderer返回一个组件对象,此组件对象可以
绘制一个包含"The Java Programming Language"字符串的节点.如果这
个cellrenderer是[code]DefaultTreeCellRenderer,那么,它会返回一个标签对象,
[/code]
[code]此标签对象上绘制了一个包含此字符串的一个叶子节点.
[/code]
Cellrenderer只能用来绘制节点,它不能处理事件.如
[code]果你想在tree中增加事件处理,你需要注册你的事件处理器.
 
[/code]
 
TreeIconDemo.java:[/b]
/**
* A 1.4 application that requires the following additional files:
*   TreeDemoHelp.html
 *arnold.html
 *bloch.html
 *chan.html
 *jls.html
 *swingtutorial.html
 *tutorial.html
 *tutorialcont.html
 *vm.html
*/
 
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
 
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.ImageIcon;
 
import java.net.URL;
import java.io.IOException;
import java.awt.Dimension;
import java.awt.GridLayout;
 
public class TreeIconDemo extends JPanel
  implements TreeSelectionListener {
private JEditorPane htmlPane;
private JTree tree;
private URL helpURL;
private static boolean DEBUG = false;
 
public TreeIconDemo() {
super(new GridLayout(1,0));
 
//Create the nodes.
DefaultMutableTreeNode top =
new DefaultMutableTreeNode("The Java Series");
createNodes(top);
 
//Create a tree that allows one selection at a time.
tree = new JTree(top);
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
 
//Set the icon for leaf nodes.
ImageIcon leafIcon = createImageIcon("images/middle.gif");
if (leafIcon != null) {
DefaultTreeCellRenderer renderer =new DefaultTreeCellRenderer();
renderer.setLeafIcon(leafIcon);
tree.setCellRenderer(renderer);
} else {
System.err.println("Leaf icon missing; using default.");
}
 
//Listen for when the selection changes.
tree.addTreeSelectionListener(this);
 
//Create the scroll pane and add the tree to it. 
JScrollPane treeView = new JScrollPane(tree);
 
//Create the HTML viewing pane.
htmlPane = new JEditorPane();
htmlPane.setEditable(false);
initHelp();
JScrollPane htmlView = new JScrollPane(htmlPane);
 
//Add the scroll panes to a split pane.
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setTopComponent(treeView);
splitPane.setBottomComponent(htmlView);
 
Dimension minimumSize = new Dimension(100, 50);
htmlView.setMinimumSize(minimumSize);
treeView.setMinimumSize(minimumSize);
splitPane.setDividerLocation(100); //XXX: ignored in some releases
   //of Swing. bug 4101306
//workaround for bug 4101306:
//treeView.setPreferredSize(new Dimension(100, 100)); 
 
splitPane.setPreferredSize(new Dimension(500, 300));
 
//Add the split pane to this panel.
add(splitPane);
}
 
/** Required by TreeSelectionListener interface.*/
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)
   tree.getLastSelectedPathComponent();
 
if (node == null) return;
 
Object nodeInfo = node.getUserObject();
if (node.isLeaf()) {
BookInfo book = (BookInfo)nodeInfo;
displayURL(book.bookURL);
if (DEBUG) {
System.out.print(book.bookURL + ":  /n");
}
} else {
displayURL(helpURL); 
}
if (DEBUG) {
System.out.println(nodeInfo.toString());
}
}
 
private class BookInfo {
public String bookName;
public URL bookURL;
 
public BookInfo(String book, String filename) {
bookName = book;
bookURL = TreeIconDemo.class.getResource(filename);
if (bookURL == null) {
System.err.println("Couldn't find file: "
   + filename);
}
}
 
public String toString() {
return bookName;
}
}
 
private void initHelp() {
String s = "TreeDemoHelp.html";
helpURL = TreeIconDemo.class.getResource(s);
if (helpURL == null) {
System.err.println("Couldn't open help file: " + s);
} else if (DEBUG) {
System.out.println("Help URL is " + helpURL);
}
 
displayURL(helpURL);
}
 
private void displayURL(URL url) {
try {
if (url != null) {
htmlPane.setPage(url);
} else { //null url
   htmlPane.setText("File Not Found");
if (DEBUG) {
System.out.println("Attempted to display a null URL.");
}
}
} catch (IOException e) {
System.err.println("Attempted to read a bad URL: " + url);
}
}
 
private void createNodes(DefaultMutableTreeNode top) {
DefaultMutableTreeNode category = null;
DefaultMutableTreeNode book = null;
 
category = new DefaultMutableTreeNode("Books for Java Programmers");
top.add(category);
 
//original Tutorial
book = new DefaultMutableTreeNode(new BookInfo
("The Java Tutorial: A Short Course on the Basics",
"tutorial.html"));
category.add(book);
 
//Tutorial Continued
book = new DefaultMutableTreeNode(new BookInfo
("The Java Tutorial Continued: The Rest of the JDK",
"tutorialcont.html"));
category.add(book);
 
//JFC Swing Tutorial
book = new DefaultMutableTreeNode(new BookInfo
("The JFC Swing Tutorial: A Guide to Constructing GUIs",
"swingtutorial.html"));
category.add(book);
 
//Bloch
book = new DefaultMutableTreeNode(new BookInfo
("Effective Java Programming Language Guide",
 "bloch.html"));
category.add(book);
 
//Arnold/Gosling
book = new DefaultMutableTreeNode(new BookInfo
("The Java Programming Language", "arnold.html"));
category.add(book);
 
//Chan
book = new DefaultMutableTreeNode(new BookInfo
("The Java Developers Almanac",
 "chan.html"));
category.add(book);
 
category = new DefaultMutableTreeNode("Books for Java Implementers");
top.add(category);
 
//VM
book = new DefaultMutableTreeNode(new BookInfo
("The Java Virtual Machine Specification",
 "vm.html"));
category.add(book);
 
//Language Spec
book = new DefaultMutableTreeNode(new BookInfo
("The Java Language Specification",
 "jls.html"));
category.add(book);
}
 
/** Returns an ImageIcon, or null if the path was invalid.*/
protected static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = TreeIconDemo.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
 
/**
 * Create the GUI and show it.  For thread safety,
 * this method should be invoked from the
 * event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
 
//Create and set up the window.
JFrame frame = new JFrame("TreeIconDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
//Create and set up the content pane.
TreeIconDemo newContentPane = new TreeIconDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
 
//Display the window.
frame.pack();
frame.setVisible(true);
}
 
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
 
 
[code]TreeIconDemo2.java
[/code]
/**
* A 1.4 application that requires the following additional files:
*   TreeDemoHelp.html
 *arnold.html
 *bloch.html
 *chan.html
 *jls.html
 *swingtutorial.html
 *tutorial.html
 *tutorialcont.html
 *vm.html
*/
 
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
 
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.ToolTipManager;
import javax.swing.ImageIcon;
import javax.swing.Icon;
 
import java.net.URL;
import java.io.IOException;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Component;
 
 
public class TreeIconDemo2 extends JPanel
   implements TreeSelectionListener {
private JEditorPane htmlPane;
private JTree tree;
private URL helpURL;
private static boolean DEBUG = false;
 
public TreeIconDemo2() {
super(new GridLayout(1,0));
 
//Create the nodes.
DefaultMutableTreeNode top =
new DefaultMutableTreeNode("The Java Series");
createNodes(top);
 
//Create a tree that allows one selection at a time.
tree = new JTree(top);
tree.getSelectionModel().setSelectionMode
(TreeSelectionModel.SINGLE_TREE_SELECTION);
 
//Enable tool tips.
ToolTipManager.sharedInstance().registerComponent(tree);
 
//Set the icon for leaf nodes.
ImageIcon tutorialIcon = createImageIcon("images/middle.gif");
if (tutorialIcon != null) {
tree.setCellRenderer(new MyRenderer(tutorialIcon));
} else {
System.err.println("Tutorial icon missing; using default.");
}
 
//Listen for when the selection changes.
tree.addTreeSelectionListener(this);
 
//Create the scroll pane and add the tree to it. 
JScrollPane treeView = new JScrollPane(tree);
 
//Create the HTML viewing pane.
htmlPane = new JEditorPane();
htmlPane.setEditable(false);
initHelp();
JScrollPane htmlView = new JScrollPane(htmlPane);
 
//Add the scroll panes to a split pane.
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setTopComponent(treeView);
splitPane.setBottomComponent(htmlView);
 
Dimension minimumSize = new Dimension(100, 50);
htmlView.setMinimumSize(minimumSize);
treeView.setMinimumSize(minimumSize);
splitPane.setDividerLocation(100); //XXX: ignored in some releases
   //of Swing. bug 4101306
//workaround for bug 4101306:
//treeView.setPreferredSize(new Dimension(100, 100)); 
 
splitPane.setPreferredSize(new Dimension(500, 300));
 
//Add the split pane to this panel.
add(splitPane);
}
 
/** Required by TreeSelectionListener interface.*/
public void valueChanged(TreeSelectionEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)
   tree.getLastSelectedPathComponent();
 
if (node == null) return;
 
Object nodeInfo = node.getUserObject();
if (node.isLeaf()) {
BookInfo book = (BookInfo)nodeInfo;
displayURL(book.bookURL);
if (DEBUG) {
System.out.print(book.bookURL + ":  /n");
}
} else {
displayURL(helpURL); 
}
if (DEBUG) {
System.out.println(nodeInfo.toString());
}
}
 
private class BookInfo {
public String bookName;
public URL bookURL;
 
public BookInfo(String book, String filename) {
bookName = book;
bookURL = TreeIconDemo.class.getResource(filename);
if (bookURL == null) {
System.err.println("Couldn't find file: "
   + filename);
}
}
 
public String toString() {
return bookName;
}
}
 
private void initHelp() {
String s = "TreeDemoHelp.html";
helpURL = TreeIconDemo.class.getResource(s);
if (helpURL == null) {
System.err.println("Couldn't open help file: " + s);
} else if (DEBUG) {
System.out.println("Help URL is " + helpURL);
}
 
displayURL(helpURL);
}
 
private void displayURL(URL url) {
try {
if (url != null) {
htmlPane.setPage(url);
} else { //null url
   htmlPane.setText("File Not Found");
if (DEBUG) {
System.out.println("Attempted to display a null URL.");
}
}
} catch (IOException e) {
System.err.println("Attempted to read a bad URL: " + url);
}
}
 
private void createNodes(DefaultMutableTreeNode top) {
DefaultMutableTreeNode category = null;
DefaultMutableTreeNode book = null;
 
category = new DefaultMutableTreeNode("Books for Java Programmers");
top.add(category);
 
//original Tutorial
book = new DefaultMutableTreeNode(new BookInfo
("The Java Tutorial: A Short Course on the Basics",
"tutorial.html"));
category.add(book);
 
//Tutorial Continued
book = new DefaultMutableTreeNode(new BookInfo
("The Java Tutorial Continued: The Rest of the JDK",
"tutorialcont.html"));
category.add(book);
 
//JFC Swing Tutorial
book = new DefaultMutableTreeNode(new BookInfo
("The JFC Swing Tutorial: A Guide to Constructing GUIs",
"swingtutorial.html"));
category.add(book);
 
//Bloch
book = new DefaultMutableTreeNode(new BookInfo
("Effective Java Programming Language Guide",
 "bloch.html"));
category.add(book);
 
//Arnold/Gosling
book = new DefaultMutableTreeNode(new BookInfo
("The Java Programming Language", "arnold.html"));
category.add(book);
 
//Chan
book = new DefaultMutableTreeNode(new BookInfo
("The Java Developers Almanac",
 "chan.html"));
category.add(book);
 
category = new DefaultMutableTreeNode("Books for Java Implementers");
top.add(category);
 
//VM
book = new DefaultMutableTreeNode(new BookInfo
("The Java Virtual Machine Specification",
 "vm.html"));
category.add(book);
 
//Language Spec
book = new DefaultMutableTreeNode(new BookInfo
("The Java Language Specification",
 "jls.html"));
category.add(book);
}
 
/** Returns an ImageIcon, or null if the path was invalid.*/
protected static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = TreeIconDemo2.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
 
/**
 * Create the GUI and show it.  For thread safety,
 * this method should be invoked from the
 * event-dispatching thread.
*/
private static void createAndShowGUI() {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
 
//Create and set up the window.
JFrame frame = new JFrame("TreeIconDemo2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
//Create and set up the content pane.
TreeIconDemo2 newContentPane = new TreeIconDemo2();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
 
//Display the window.
frame.pack();
frame.setVisible(true);
}
 
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
 
private class MyRenderer extends DefaultTreeCellRenderer {
Icon tutorialIcon;
 
public MyRenderer(Icon icon) {
tutorialIcon = icon;
}
 
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 && isTutorialBook(value)) {
setIcon(tutorialIcon);
setToolTipText("This book is in the Tutorial series.");
} else {
setToolTipText(null); //no tool tip
}
 
return this;
}
 
protected boolean isTutorialBook(Object value) {
DefaultMutableTreeNode node =
(DefaultMutableTreeNode)value;
BookInfo nodeInfo = 
(BookInfo)(node.getUserObject());
String title = nodeInfo.bookName;
if (title.indexOf("Tutorial") >= 0) {
return true;
} 
 
return false;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: