如何使用JTree

如何使用JTree,第1张

如何使用 Jtree (1)创建树 (2)对节点的选择做出响应 (3)自定义树的外观表现 (4)动态改变一棵树 (5)创建树的数据模型 (6)懒加载孩子 (7)如何写 expansion linstener (8)如何写 tree-will-expand listener 利用 JTree 类, 你可以显示等级体系的数据。 一个 JTree 对象并没有包含实际的数据; 它只是提供了数据的一个视图。像其他非平凡的( nontrivial ) Swing 组件一样,这 种 Jtree 通过查询她的数据模型获得数据。这是一个 Jtree : 如上面的图片所显示, Jtree 垂直显示它的数据。树中显示的每一行包含一项数据,称 之为节点( node )。每颗树有一个根节点( root node ),其他所有节点是它的子孙。默 认情况下,树只显示根节点,但是你可以设置改变默认显示方式。一个节点可以拥有孩子也 可以不拥有任何子孙。我们称那些可以拥有孩子(不管当前是否有孩子)的节点为“分支节 点”( 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 . 在树中, 一个节点可以通过 TreePath(一个囊括该节点和他所有祖先节点的路径对象) 或者他的折叠行来识别。 展开节点( expanded node )就是一个非叶子节点,当他的所有祖先都展开时,他将 显示他的孩子。 折叠节点( collapsed node )是隐藏了孩子们得的节点。 隐藏节点( hidden node )就是折叠节点下的一个孩子 (1)创建一棵 Tree 这里是一个应用程序的截图,上半部分展示了一个滚动面板( scroll pane )中的树 ( Jtree )。 接下来的代码是从 http://download.oracle.com/javase/tutorial/uiswing/examples/components/TreeDemoProj ect/src/components/TreeDemo.java 获得,创建了一个 JTree 对象,并将之放到一个 scroll pane 上 Java 代码 1. //Where instance variables are declared: 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. ... } private JTree tree... public TreeDemo() { ... DefaultMutableTreeNode top = new DefaultMutableTreeNode("The Java Series")createNodes(top)tree = new JTree(top)... JScrollPane treeView = new JScrollPane(tree)这段代码创建了一个 DefaultMutableTreeNode 实例作为根节点。 接着创建树中剩下的其 他节点。创建完节点后,通过指定刚才创建的根节点为 JTree 构造函数的参数,创建一棵 树。最后,将树放到滚动面板中,这是一个通常的策略,因为需要显示完一个树,而展开树 需要另外比较大的空间。 以下代码创建根节点以下的节点 Java 代码 1. private void createNodes(DefaultMutableTreeNode top) { 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. } //Language Spec book = new DefaultMutableTreeNode(new BookInfo ("The Java Language Specification", "jls.html"))category.add(book)//VM book = new DefaultMutableTreeNode(new BookInfo ("The Java Virtual Machine Specification", "vm.html"))category.add(book)category = new DefaultMutableTreeNode("Books for Java Implementers")top.add(category)//...add more books for programmers... //JFC Swing Tutorial book = new DefaultMutableTreeNode(new BookInfo ("The JFC Swing Tutorial: A Guide to Constructing GUIs", "swingtutorial.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)//original Tutorial book = new DefaultMutableTreeNode(new BookInfo ("The Java Tutorial: A Short Course on the Basics", "tutorial.html"))category.add(book)category = new DefaultMutableTreeNode("Books for Java Programmers")top.add(category)DefaultMutableTreeNode category = nullDefaultMutableTreeNode book = nullDefaultMutableTreeNode 构造函数的参数是一个用户自定义的类对象,它包含或指向 了关联树节点的数据。这个用户对象可以是一个字符串,或者是一个自定义的类。如果它实 现了一个自定义对象, 你应该要重新实现覆盖他的 toString 方法, 这样他才能返回对应字符 串作为节点显示的字符串。Jtree 默认情况下, 每个节点都是用 toString 的返回值作为显示。 所以, toString 返回一些有意义的值是很重要的。 让 有时候, 覆盖 toString 方法是不可行的; 在某些场景你可以通过重写 Jtree 的 convertValueToText 方法,映射模型对象到一个可显 示的字符串。 例如,前面 demo 中的 BookInfo 类是一个自定义类,它包含了两个字段:书名和描述 该书本的 HTML 文件的 URL 路径。 toString 方法也重新实现,返回书名。从而,每个节点 关联了一个 BookInfo 对象,并且显示书名。 总之,你可以调用 Jtree 的构造函数创建一棵树,指定一个实现了 TreeNode 的类作为 参数。你应该尽量把这棵树放到一个滚动面板中( scroll pane ),这样树就不会占用太大 的空间。对于树节点相应用户点击而展开和折叠的功能,你不需要做任何事情。但是,你一 定要添加一些代码使得树在用户点击选择一个节点时能够作出反应,例如: (2)对节点的选择作出响应 对于树节点的选择做出响应是简单的。 你可以实现一个树节点选择监听器, 并且注册在这棵 树上。接下来的代码显示了 TreeDemo.java 中有关选择的代码: Java 代码 1. //Where the tree is initialized: 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Object nodeInfo = node.getUserObject()if (node.isLeaf()) { BookInfo book = (BookInfo)nodeInfoif (node == null) //Nothing is selected. return//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 se lection. DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent()tree.getSelectionModel().setSelectionMode (TreeSelectionModel.SINGLE_TREE_SELECTION)21. 22. 23. 24. 25. } } displayURL(book.bookURL)} else { displayURL(helpURL)上面的代码执行了一下任务: 1 .获得树的默认 TreeSelectionModel (节点选择模式),然后设置它,使得在某一 时刻只有一个节点被选中。 2 .注册了一个事件处理器。事件处理器是一个实现了 TreeSelectionListener 接口的 对象。 3. 在事件处理器中,通过调用 Tree 的 getLastSelectedPathComponent 方法获得选中 的节点。 4 .使用 getUserObject 方法获得节点关联的数据。(节点 node 是一个非平凡组件, 要通过它关联的数据模型获得真正的数据) 这里给出一些树节点的图片,分别通过 Java 、 Windows 和 MacOS 样式绘得。 (依次为 java look 、 windows look 和 MacOS look ) 像之前图片显示一样,一棵树按照惯例,对于每个基点显示了一个图标和一些文字。像 我们简短的展示一样,你可以指定这些样式。 一棵树通常表现一些外观和样式特效, 通过不同的绘制图形指示节点间的关系。 你可以 在限制范围内自定义这些图形。首先,你可以使用 tree.setRootVisible(true) 设置显示根节 点或者 tree.setRootVisible(false) 隐藏根节点。其次,你可以使 用 tree.setShowsRootHandles(true) 请求设置树的顶层节点具有句柄( +- 图标,点击句柄 使其展开折叠)。如果顶层节点是根节点的话,需要保证它是可视的,如果是顶层节点则每 个孩子都显示句柄。 如果你使用 Java 样式,你可以自定是否在节点间显示行线来表现他们的关系。默认情 况下, Java 样式使用“角线”(类似“ L ”)。通过设置 Jtree.lineStyle 的客户端属性,你可以 指定一种不同的标准。例如,通过以下代码,这只 JAVA 样式仅使用水平线隔开一组节点: Java 代码 1. tree.putClientProperty(“Jtree.lineStyle”, “Horizontal”)指定 JAVA 样式在节点间不显示任何行线,则使用以下代码: Java 代码 1. tree.putClientProperty(“Jtree.lineStyle”, “None”)(3)自定义树的外观表现 接下来的一些截图显示了设置不同的 Jtree.lineStyle 属性(使用 JAVA 样式) 不管你使用那种样式( java 、 windows 、 mac ) , 默认情况下,节点显示的图标决 定于节点是否为叶子节点和是否可展开。例如,在 windwos 样式中,每个叶子节点的默认 图标是一个点;在 JAVA 样式中,叶子节点默认图标是一个类似白纸的符号。在所有样式 中,分支节点被一个文件夹符号所标识。不同样式对于可展开分支和对应的可折叠分支,可 能有不同的图标。 你可以很容易的改变叶子节点、可展开分支节点和可折叠分支节点的默认图标。 如果要 这样做的话,首先,你要创建一个 DefaultTreeCellRenderer 实例。你总是可以创建自己 的 TreeCellRender ,让你喜欢的任何组件重复利用。接着,通过调用以下一个或多个方法 去指定图标: setLeafIcon (对于叶子节点), setOpenIcon (对于可展开分支节 点), setClosedIcon (对于可折叠节点)。如果你想要这棵树中各种节点都不显示图标, 你就要指定图标为 null 。 一定你创建了这些图标,使用树的 setCellRender 方法去指定这 个 DefaultTreeCellRender 来绘制它的节点。这里有一个来自 TreeIconDemo 的例子 Java 代码 1. ImageIcon leafIcon = createImageIcon("images/middle.gif")2. if (leafIcon != null) { 3. 4. 5. 6. DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer()renderer.setLeafIcon(leafIcon)tree.setCellRenderer(renderer)7. } 这是一个截图: 如果你想更精巧的控制节点图标,或者你想提供一些工具,你可以创 建 DefaultTreeCellRender 的子类,然后覆盖他的 getTreeCellRendererComponent 方法。 因为 DefaultTreeCellRenderer 是 Jlabel 的一个子类,你可以使用任何 Jlabel 的方法,例如 setIcon 。 下面代码来自 TreeIconDemo2.java ,创建了一个单元绘制器( cell renderer ),它根 据节点的文本数据是否包含单词“ Tutorial ”来改变了叶子节点的图标。 这个 renderer 同样可 以指定提示文本( tool-tip ) --- 鼠标移到上面,出现提示。

用new JScrollPane(Component)。其中Component是你要放到滚动条中的组件,下面是一个示例程序,你可以运行一下。

import java.awt.*

import javax.swing.*

public class Tree extends JApplet {

public void init() {

UIManager.put("Tree.background", Color.LIGHT_GRAY)

UIManager.put("Tree.textBackground", Color.LIGHT_GRAY)

UIManager.put("Tree.line",Color.red)

UIManager.put("ScrollBar.width", new Integer(20))

getContentPane().add(new JScrollPane(new JTree()))

//UIManager.put("Button.foreground", Color.red)

// getContentPane().add(new JTree())

// getContentPane().add(new JButton())

//getContentPane().add(new JScrollPane(new JTree()))

}

}

import javax.swing.JFrame

import javax.swing.JOptionPane

import javax.swing.JScrollPane

import javax.swing.JTree

import javax.swing.ScrollPaneConstants

import javax.swing.UIManager

import javax.swing.UnsupportedLookAndFeelException

import javax.swing.event.TreeSelectionEvent

import javax.swing.event.TreeSelectionListener

import javax.swing.tree.DefaultMutableTreeNode

import javax.swing.tree.DefaultTreeModel

/**

*

* @author 逝水

*

*/

public class JTreeDemo extends JFrame implements TreeSelectionListener{

private static final long serialVersionUID = -6209666185329417356L

//树组件

protected JTree jTree 

public JTreeDemo(){

init()

}

//初始化

private void init() {

jTree =  new JTree()

//树节点的相关数据

DefaultMutableTreeNode root = new DefaultMutableTreeNode("三国名将")

DefaultMutableTreeNode shu = new DefaultMutableTreeNode("蜀国")

DefaultMutableTreeNode wei = new DefaultMutableTreeNode("魏国")

DefaultMutableTreeNode wu = new DefaultMutableTreeNode("吴国")

shu.add(new DefaultMutableTreeNode("关羽"))

shu.add(new DefaultMutableTreeNode("张飞"))

shu.add(new DefaultMutableTreeNode("赵云"))

shu.add(new DefaultMutableTreeNode("马超"))

shu.add(new DefaultMutableTreeNode("黄忠"))

wei.add(new DefaultMutableTreeNode("张辽"))

wei.add(new DefaultMutableTreeNode("典韦"))

wei.add(new DefaultMutableTreeNode("夏侯惇"))

wei.add(new DefaultMutableTreeNode("许褚"))

wei.add(new DefaultMutableTreeNode("徐晃"))

wu.add(new DefaultMutableTreeNode("太史慈"))

wu.add(new DefaultMutableTreeNode("甘宁"))

wu.add(new DefaultMutableTreeNode("孙策"))

wu.add(new DefaultMutableTreeNode("周瑜"))

wu.add(new DefaultMutableTreeNode("陆逊"))

root.add(shu)

root.add(wei)

root.add(wu)

//树的数据模型

DefaultTreeModel model = new DefaultTreeModel(root)

//设置数据模型

jTree.setModel(model)

// 展开所有树

for (int i = 0 i < jTree.getRowCount() i++)

jTree.expandRow(i)

//添加事件

jTree.addTreeSelectionListener(this)

//滚动面板

JScrollPane jScrollPane = new JScrollPane(jTree,

ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,

ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER)

//添加树到滚动面板

jScrollPane.getViewport().add(jTree)

//添加滚动面板到窗口中

this.getContentPane().add(jScrollPane)

this.setTitle("JTree的事件例子")

this.pack()

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)

}

public static void main(String[] args){

//Windows风格

//String lookAndFeel = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"

//Windows Classic风格

//String lookAndFeel = "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"

//系统当前风格

String lookAndFeel = UIManager.getSystemLookAndFeelClassName()

try {

UIManager.setLookAndFeel(lookAndFeel)

} catch (ClassNotFoundException e) {

e.printStackTrace()

} catch (InstantiationException e) {

e.printStackTrace()

} catch (IllegalAccessException e) {

e.printStackTrace()

} catch (UnsupportedLookAndFeelException e) {

e.printStackTrace()

}

JTreeDemo demo = new JTreeDemo()

demo.setVisible(true)

}

@Override

public void valueChanged(TreeSelectionEvent e) {

//获取选择的节点

DefaultMutableTreeNode node = (DefaultMutableTreeNode) jTree

.getLastSelectedPathComponent()

if(node.getLevel() == 0){

//显示提示信息

JOptionPane.showMessageDialog(null,

node.getUserObject()+": 共"+node.getChildCount()+"个国家")

}else if(node.getLevel() == 1){

//显示提示信息

JOptionPane.showMessageDialog(null,

node.getUserObject()+": 共"+node.getChildCount()+"名名将")

}else if(node.getLevel() == 2){

//显示提示信息

JOptionPane.showMessageDialog(null, node.getParent()+"名将: "+

node.getUserObject())

}

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11509206.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-16
下一篇 2023-05-16

发表评论

登录后才能评论

评论列表(0条)

保存