(一)怎么使用JTree

(一)如何使用JTree利用JTree类,你可以显示等级体系的数据。一个JTree对象并没有包含实际的数据;它只是提供

(一)如何使用JTree

利用JTree类,你可以显示等级体系的数据。一个JTree对象并没有包含实际的数据;它只是提供了数据的一个视图。像其他非平凡的(nontrivial)Swing组件一样,这种Jtree通过查询她的数据模型获得数据。这是一个Jtree:


(一)怎么使用JTree

如上面的图片所显示,Jtree垂直显示它的数据。树中显示的每一行包含一项数据,称之为节点(node)。每颗树有一个根节点(rootnode),其他所有节点是它的子孙。默认情况下,树只显示根节点,但是你可以设置改变默认显示方式。一个节点可以拥有孩子也可以不拥有任何子孙。我们称那些可以拥有孩子(不管当前是否有孩子)的节点为“分支节点”(branch nodes),而不能拥有孩子的节点为“叶子节点”(leaf nodes)。

分支节点可以有任意多个孩子。通常,用户可以通过点击实现展开或者折叠分支节点,使得他们的孩子可见或者不可见。默认情况下,除了根节点以外的所有分支节点默认呈现折叠状态。程序中,通过监听 tree expansion 或者 tree-will-expand事件可以检测分支节点的展开状态。监听事件在下面两节内容中描述How to Write a Tree Expansion Listener and How to Write a Tree-Will-Expand Listener.

//Where instance variables are declared:private JTree tree;...public TreeDemo() { ... DefaultMutableTreeNode top = new DefaultMutableTreeNode("The Java Series"); createNodes(top); tree = new JTree(top); ... JScrollPane treeView = new JScrollPane(tree); ...}?

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); //...add more books for programmers... 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);}?

//Where the tree is initialized: tree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION);//Listen for when the selection changes. tree.addTreeSelectionListener(this);...public void valueChanged(TreeSelectionEvent e) {//Returns the last path element of the selection.//This method is useful only when the selection model allows a single selection. DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); if (node == null) //Nothing is selected. return; Object nodeInfo = node.getUserObject(); if (node.isLeaf()) { BookInfo book = (BookInfo)nodeInfo; displayURL(book.bookURL); } else { displayURL(helpURL); }}?

?

这里给出一些树节点的图片,分别通过Java、Windows和MacOS样式绘得。


(一)怎么使用JTree

像之前图片显示一样,一棵树按照惯例,对于每个基点显示了一个图标和一些文字。像我们简短的展示一样,你可以指定这些样式。

tree.putClientProperty(“Jtree.lineStyle”, “Horizontal”);

tree.putClientProperty(“Jtree.lineStyle”, “None”);?(3)自定义树的外观表现

不管你使用那种样式(java、windows、mac),默认情况下,节点显示的图标决定于节点是否为叶子节点和是否可展开。例如,在windwos样式中,每个叶子节点的默认图标是一个点;在JAVA样式中,叶子节点默认图标是一个类似白纸的符号。在所有样式中,分支节点被一个文件夹符号所标识。不同样式对于可展开分支和对应的可折叠分支,可能有不同的图标。

ImageIcon leafIcon = createImageIcon("images/middle.gif");if (leafIcon != null) { DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer(); renderer.setLeafIcon(leafIcon); tree.setCellRenderer(renderer);}

?


(一)怎么使用JTree

??? 如果你想更精巧的控制节点图标,或者你想提供一些工具,你可以创建DefaultTreeCellRender的子类,然后覆盖他的getTreeCellRendererComponent方法。因为DefaultTreeCellRenderer是Jlabel的一个子类,你可以使用任何Jlabel的方法,例如setIcon。

//...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; }}?

?


(一)怎么使用JTree

你可能会疑惑单元绘制器(cellrenderer)是如何工作的。当一个tree在话每个节点的时候,不管是Jtree或是他的样式表现都包含了绘制节点的代码。Tree可以使用cellrenderer的绘图代码代替前者去绘制节点。例如,画一个包含字符串“The Java Programming Language”的叶子节点,tree会要求cell renderer返回一个组件,该组件能够绘制一个包含该字符串的叶子节点。如果这个cell renderer是一个DefaultTreeCellRender,它就返回一个label(DefaultTreeCellRender继承于Jlabel),它绘制默认的叶子节点图标,紧随一段字符串。

接下来的图片展示了一个叫DynamicTreeDemo的应用程序,它允许你从一颗可视tree中增加或者移除节点。你也可以编辑每个节点的文本。


(一)怎么使用JTree

rootNode = new DefaultMutableTreeNode("Root Node");treeModel = new DefaultTreeModel(rootNode);treeModel.addTreeModelListener(new MyTreeModelListener());tree = new JTree(treeModel);tree.setEditable(true);tree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION);tree.setShowsRootHandles(true); ?

class MyTreeModelListener implements TreeModelListener { public void treeNodesChanged(TreeModelEvent e) { DefaultMutableTreeNode node; node = (DefaultMutableTreeNode) (e.getTreePath().getLastPathComponent()); /* * If the event lists children, then the changed * node is the child of the node we have already * gotten. Otherwise, the changed node and the * specified node are the same. */ try { int index = e.getChildIndices()[0]; node = (DefaultMutableTreeNode) (node.getChildAt(index)); } catch (NullPointerException exc) {} System.out.println("The user has finished editing the node."); System.out.println("New value: " + node.getUserObject()); } public void treeNodesInserted(TreeModelEvent e) { } public void treeNodesRemoved(TreeModelEvent e) { } public void treeStructureChanged(TreeModelEvent e) { }}

treePanel.addObject("New Node " + newNodeSuffix++);...public DefaultMutableTreeNode addObject(Object child) { DefaultMutableTreeNode parentNode = null; TreePath parentPath = tree.getSelectionPath(); if (parentPath == null) { //There is no selection. Default to the root node. parentNode = rootNode; } else { parentNode = (DefaultMutableTreeNode) (parentPath.getLastPathComponent()); } return addObject(parentNode, child, true);}...public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent, Object child, boolean shouldBeVisible) { DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child); ... treeModel.insertNodeInto(childNode, parent, parent.getChildCount()); //Make sure the user can see the lovely new node. if (shouldBeVisible) { tree.scrollPathToVisible(new TreePath(childNode.getPath())); } return childNode;}?


(一)怎么使用JTree

GenealogyModel.java中,你可以找到这个自定义的tree model的实现。因为这个model通过一个DefaultTreeModel的子类实现,他必须实现TreeModel接口。这就需要实现获得节点信息的一系列方法,例如,哪个是根节点、某个节点的子孙是哪些节点。在GenealogyModel的例子中,每个节点表现为一个Person类型的对象,这是一个未实现TreeNode接口的自定义类。

class DemoArea extends JScrollPane implements TreeWillExpandListener { ....... ....... private TreeNode createNodes() { DefaultMutableTreeNode root; DefaultMutableTreeNode grandparent; DefaultMutableTreeNode parent; root = new DefaultMutableTreeNode("San Francisco"); grandparent = new DefaultMutableTreeNode("Potrero Hill"); root.add(grandparent); parent = new DefaultMutableTreeNode("Restaurants"); grandparent.add(parent); dummyParent = parent; return root; } ?

TreeNode rootNode = createNodes();tree = new JTree(rootNode); tree.addTreeExpansionListener(this);tree.addTreeWillExpandListener(this);....... ....... setViewportView(tree);?

private void LoadLazyChildren(){ DefaultMutableTreeNode child; child = new DefaultMutableTreeNode("Thai Barbeque"); dummyParent.add(child); child = new DefaultMutableTreeNode("Goat Hill Pizza"); dummyParent.add(child); textArea.append(" Thai Barbeque and Goat Hill Pizza are loaded lazily");}..............public void treeWillExpand(TreeExpansionEvent e) throws ExpandVetoException { saySomething("You are about to expand node ", e); int n = JOptionPane.showOptionDialog( this, willExpandText, willExpandTitle, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, willExpandOptions, willExpandOptions[1]); LoadLazyChildren();}

?

(7)如何写TreeExpansion Listener(监听器)


(一)怎么使用JTree

private void LoadLazyChildren(){ DefaultMutableTreeNode child; child = new DefaultMutableTreeNode("Thai Barbeque"); dummyParent.add(child); child = new DefaultMutableTreeNode("Goat Hill Pizza"); dummyParent.add(child); textArea.append(" Thai Barbeque and Goat Hill Pizza are loaded lazily");}..............public void treeWillExpand(TreeExpansionEvent e) throws ExpandVetoException { saySomething("You are about to expand node ", e); int n = JOptionPane.showOptionDialog( this, willExpandText, willExpandTitle, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, willExpandOptions, willExpandOptions[1]); LoadLazyChildren();}?(8)如何写Tree-Will-ExpandListener

  
哈哈,非常受用!谢了!