如何用JTree 把一颗多叉树变成图形:

如何使用JTree~

  如何使用 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 )就是折叠节点下的一个孩子 \f(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 代码 \f1. 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 = null; DefaultMutableTreeNode book = null; \fDefaultMutableTreeNode 构造函数的参数是一个用户自定义的类对象,它包含或指向 了关联树节点的数据。这个用户对象可以是一个字符串,或者是一个自定义的类。如果它实 现了一个自定义对象, 你应该要重新实现覆盖他的 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)nodeInfo; if (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); \f21. 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 代码 \f1. 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); \f7. } 这是一个截图: 如果你想更精巧的控制节点图标,或者你想提供一些工具,你可以创 建 DefaultTreeCellRender 的子类,然后覆盖他的 getTreeCellRendererComponent 方法。 因为 DefaultTreeCellRenderer 是 Jlabel 的一个子类,你可以使用任何 Jlabel 的方法,例如 setIcon 。 下面代码来自 TreeIconDemo2.java ,创建了一个单元绘制器( cell renderer ),它根 据节点的文本数据是否包含单词“ Tutorial ”来改变了叶子节点的图标。 这个 renderer 同样可 以指定提示文本( tool-tip ) --- 鼠标移到上面,出现提示。

/** * 把代码复制到文件,可以运行。 */import java.awt.BorderLayout;import java.awt.Color;import java.awt.Component;import java.awt.Font;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Rectangle;import java.awt.Transparency;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.awt.image.BufferedImage;import javax.swing.Icon;import javax.swing.ImageIcon;import javax.swing.JDialog;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTree;import javax.swing.UIManager;import javax.swing.tree.DefaultMutableTreeNode;import javax.swing.tree.TreeCellRenderer;/** * * @author beans */public class TreeMain { public static void main(String[] args) { new TreeMain().showDialog(); } public TreeMain() { } /** * 显示窗口 */ private void showDialog() { JDialog dialog = new JDialog(); dialog.setBounds(new Rectangle(50, 50, 380, 280)); dialog.setTitle("演示树"); dialog.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { dialog.setVisible(false); dialog.dispose(); } }); dialog.add(this.getPanel(), BorderLayout.CENTER); dialog.setVisible(true); } private JPanel getPanel() { JPanel panel = new JPanel(); JScrollPane treePanel = new JScrollPane(); treePanel.setViewportView(this.getTree()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(panel); panel.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(treePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(treePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 272, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap(18, Short.MAX_VALUE)) ); panel.add(treePanel, BorderLayout.CENTER); return panel; } /** * 取得树。 * * @return */ private JTree getTree() { DefaultMutableTreeNode root = new DefaultMutableTreeNode(); root.add(this.getNode()); root.add(this.getNode()); root.add(this.getNode()); JTree jtree = new JTree(root); jtree.setRootVisible(false); jtree.setCellRenderer(new CTreeCellRenderer()); jtree.expandRow(1); return jtree; } /** * 取得树节点。 * * @return */ private DefaultMutableTreeNode getNode() { DefaultMutableTreeNode node = new DefaultMutableTreeNode(new NodeObject(true, "节")); for (int i = 0; i < 5; i++) { DefaultMutableTreeNode leaf = new DefaultMutableTreeNode(new NodeObject(false, "叶" + i)); node.add(leaf); } return node; } /** * 树节点和树叶,关联对象。 */ class NodeObject { boolean isNode; String name; /** * * @param isNode the value of isNode * @param name the value of name */ NodeObject(boolean isNode, String name) { this.isNode = isNode; this.name = name; } /** * 图标 * * @param isSelect 选中节点时返回不同的图标。 * @return */ ImageIcon getIcon(boolean isSelect) { int wh = 20; BufferedImage image = new BufferedImage(wh, wh, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = image.createGraphics(); image = g2.getDeviceConfiguration().createCompatibleImage(wh, wh, Transparency.TRANSLUCENT); Graphics2D g2d = image.createGraphics(); Font font = new Font("Dialog", Font.PLAIN, wh - 4); g2d.setFont(font); g2d.setBackground(Color.WHITE); g2d.setColor(Color.BLACK); g2d.drawString(isSelect ? " S " : " N ", 0, wh - 1); g2d.setColor(this.isNode ? Color.RED : Color.YELLOW); g2d.drawLine(0, 5, wh, 5); g2d.drawLine(0, 10, wh, 10); g2d.drawLine(0, 15, wh, 15); g2d.dispose(); g2.dispose(); return new ImageIcon(image); } String getName() { return this.name; } } /** * 树渲染器 */ protected class CTreeCellRenderer extends JLabel implements TreeCellRenderer { protected Color m_textSelectionColor; protected Color m_textNonSelectionColor; protected Color m_bkSelectionColor; protected Color m_bkNonSelectionColor; protected Color m_borderSelectionColor; protected boolean m_selected; public CTreeCellRenderer() { m_textSelectionColor = UIManager.getColor("Tree.selectionForeground"); m_textNonSelectionColor = UIManager.getColor("Tree.textForeground"); m_bkSelectionColor = UIManager.getColor("Tree.selectionBackground"); m_bkNonSelectionColor = UIManager.getColor("Tree.textBackground"); m_borderSelectionColor = UIManager.getColor("Tree.selectionBorderColor"); } @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; NodeObject obj = (NodeObject) node.getUserObject(); this.setIcon(obj.getIcon(selected)); this.setText(" " + obj.getName() + " "); this.setForeground(selected ? m_textSelectionColor : m_textNonSelectionColor); this.setBackground(selected ? m_bkSelectionColor : m_bkNonSelectionColor); this.m_selected = selected; return this; } @Override public void paint(Graphics g) { Color bColor = this.getBackground(); Icon icon = this.getIcon(); g.setColor(bColor); int offset = 0; if (icon != null && getText() != null) { offset = (icon.getIconWidth() + this.getIconTextGap()); } g.fillRect(offset, 0, this.getWidth() - 1 - offset, this.getHeight() - 1); if (this.m_selected) { g.setColor(this.m_borderSelectionColor); g.drawRect(offset, 0, this.getWidth() - 1 - offset, this.getHeight() - 1); } super.paint(g); } }}

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;

public class JTreePrintExample extends JFrame {

JTree tree;

public JTreePrintExample() {
tree = new JTree();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(400, 500);
this.add(tree);

//Expanding rows
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
setVisible(true);
saveImage();
}

void saveImage() {
BufferedImage image = new BufferedImage(tree.getWidth(), tree.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
tree.paint(g);
g.dispose();

// File to save output Image
File imageOut = new File("Jtree.png");
try {
ImageIO.write(image, "png", imageOut);
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}

public static void main(String args[]) {
new JTreePrintExample();
}
}

我不会告诉你你问错认了的0 0 我是个白痴啊啊啊。。。。

相关兴趣推荐

IT评价网,数码产品家用电器电子设备等点评来自于网友使用感受交流,不对其内容作任何保证

联系反馈
Copyright© IT评价网