import javax.swing.JEditorPane;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JSplitPane;

import javax.swing.UIManager;

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 java.net.URL;

import java.io.IOException;

import java.awt.Dimension;

import java.awt.GridLayout;

public class TreeDemo extends JPanel

implements TreeSelectionListener {

private JEditorPane htmlPane;

private JTree tree;

private URL helpURL;

private static boolean DEBUG = false;

//可选项，选择显示行的款式. 可选值为

//"Angled" (默认), "Horizontal", and "None".

private static boolean playWithLineStyle = false;

private static String lineStyle = "Horizontal";

//可选项，设置外观.

private static boolean useSystemLookAndFeel = false;

public TreeDemo() {

super(new GridLayout(1,0));

//创建一个节点

DefaultMutableTreeNode top =

new DefaultMutableTreeNode("Java 丛书");

createNodes(top);

//创建一个树,容许一次选择一项.

tree = new JTree(top);

tree.getSelectionModel().setSelectionMode

(TreeSelectionModel.SINGLE_TREE_SELECTION);

//当选择改变的时候把它列表出来

tree.addTreeSelectionListener(this);

if (playWithLineStyle) {

System.out.println("line style = " + lineStyle);

tree.putClientProperty("JTree.lineStyle", lineStyle);

}

//创建滚条窗格 ,并把所创建的树放到里面

JScrollPane treeView = new JScrollPane(tree);

//创建 HTML 视图窗格

htmlPane = new JEditorPane();

htmlPane.setEditable(false);

initHelp();

JScrollPane htmlView = new JScrollPane(htmlPane);

//把这个滚条窗格放到切分窗格里

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);

splitPane.setPreferredSize(new Dimension(500, 300));

//把这个切分窗格放到面板里

add(splitPane);

}

/**TreeSelectionListener 接口所必须. */

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 = TreeDemo.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 = TreeDemo.class.getResource(s);

if (helpURL == null) {

System.err.println("无法打开帮助文件: " + s);

} else if (DEBUG) {

System.out.println("帮助文件的 URL 是： " + helpURL);

}

displayURL(helpURL);

}

private void displayURL(URL url) {

try {

if (url != null) {

htmlPane.setPage(url);

} else { //null url

htmlPane.setText("文件没有找到");

if (DEBUG) {

System.out.println("尝试显示一个 null URL.");

}

}

} catch (IOException e) {

System.err.println("尝试去读一个坏的 URL: " + url);

}

}

private void createNodes(DefaultMutableTreeNode top) {

DefaultMutableTreeNode category = null;

DefaultMutableTreeNode book = null;

category = new DefaultMutableTreeNode("Java 程序员书籍");

top.add(category);

book = new DefaultMutableTreeNode(new BookInfo

("Java 基础教程",

"tutorial.html"));

category.add(book);

//Tutorial Continued

book = new DefaultMutableTreeNode(new BookInfo

("学习 JDK",

"tutorialcont.html"));

category.add(book);

//JFC Swing Tutorial

book = new DefaultMutableTreeNode(new BookInfo

("JFC/Swing 教程",

"swingtutorial.html"));

category.add(book);

//Bloch

book = new DefaultMutableTreeNode(new BookInfo

("高效 Java 编程指南",

"bloch.html"));

category.add(book);

//Arnold/Gosling

book = new DefaultMutableTreeNode(new BookInfo

("Java 编程语言", "arnold.html"));

category.add(book);

//Chan

book = new DefaultMutableTreeNode(new BookInfo

("Java 开发者",

"chan.html"));

category.add(book);

category = new DefaultMutableTreeNode("Java 的实现");

top.add(category);

//VM

book = new DefaultMutableTreeNode(new BookInfo

("Java 虚拟机说明",

"vm.html"));

category.add(book);

//Language Spec

book = new DefaultMutableTreeNode(new BookInfo

("Java 语言说明",

"jls.html"));

category.add(book);

}

/**

* 创建并显示这个 GUI，由事件分配线程来处理。

*/

private static void createAndShowGUI() {

if (useSystemLookAndFeel) {

try {

UIManager.setLookAndFeel(

UIManager.getSystemLookAndFeelClassName());

} catch (Exception e) {

System.err.println("Couldn't use system look and feel.");

}

}

//创建并设置窗口

JFrame frame = new JFrame("TreeDemo");

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//创建并设置 content 面板

TreeDemo newContentPane = new TreeDemo();

newContentPane.setOpaque(true);

frame.setContentPane(newContentPane);

//显示这个窗口

frame.pack();

frame.setVisible(true);

}

public static void main(String[] args) {

//给事件分配线程一个作业：创建并显示这个 GUI

javax.swing.SwingUtilities.invokeLater(new Runnable() {

public void run() {

createAndShowGUI();

}

});

}

}