现在的位置: 首页 > 综合 > 正文

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

2013年09月06日 ⁄ 综合 ⁄ 共 12173字 ⁄ 字号 评论关闭

个性化树显示

     如前所述,树的每一个节点通常有一个图标和一些文字.你可以定制这些图标和文字.

     一个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风格下,叶子节点的默认图标却是一个纸
张图标.在我们展示的所有风格样式中,分支节点的默认图标是一个文
件夹图标.在展开或者收缩分支节点时,有些节点图标也有可能显示略
有不同.
    我们可以非常容易的改变默认的图标.首先,增加一个DefaultTreeCellRenderer
的实例;然后,调用一下方法来指定你要采用的图标:
setLeafIcon (设置叶子节点), setOpenIcon (设置展开的分支节点), 
setClosedIcon (设置收缩的分支节点).如果你不想让任何节点有图标,
只需设置每个图标为null就可以了.一旦设置好图标,就可以用tree的
setCellRenderer方法来指定DefaultTreeCellRenderer渲染节点.
下面是一个例子,选自TreeIconDemo.java(后附其源代码)

ImageIcon leafIcon = createImageIcon("images/middle.gif");
if (leafIcon != null) {
    DefaultTreeCellRenderer renderer = 
        new DefaultTreeCellRenderer();
    renderer.setLeafIcon(leafIcon);
    tree.setCellRenderer(renderer);
}
如果你想更好的控制节点图标或者你想提供一个提示信息,那么你
需要增加一个DefaultTreeCellRenderer的子类并且重载
getTreeCellRendererComponen方法.因为DefaultTreeCellRenderer
是JLabel的子类,所以你可以用JLabel的所有方法---比如setIcon----来
个性化DefaultTreeCellRenderer.
     下面的代码,来自TreeIconDemo2.java,,增加一个cellrenderer,通
过判断节点文字中是否包含”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;
    }
}
你也许会奇怪: cell renderer是如何工作的.当一个tree绘出每一
个节点时,既不是JTree,也不是风格样式包含执行绘制节点的代码.
相反,tree是通过调用cellrenderer的绘制代码来完成节点的绘制的.
例如:为了绘制一个含有字符串"The Java Programming Language"的
节点,tree会让它的cellrenderer返回一个组件对象,此组件对象可以
绘制一个包含"The Java Programming Language"字符串的节点.如果这
个cellrenderer是DefaultTreeCellRenderer,那么,它会返回一个标签对象,
此标签对象上绘制了一个包含此字符串的一个叶子节点.

    Cellrenderer只能用来绘制节点,它不能处理事件.如
果你想在tree中增加事件处理,你需要注册你的事件处理器.

 

 

TreeIconDemo.java:

/**
 * 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();
            }
        });
    }
}

 

 

TreeIconDemo2.java

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

抱歉!评论已关闭.