【问题标题】:Making a JTree leaf appear as an empty directory and not a file使 JTree 叶显示为空目录而不是文件
【发布时间】:2012-11-24 16:11:36
【问题描述】:

我正在学习如何使用 Java JTree,但我遇到了一个我无法弄清楚的小问题。 使用我在 Oracle 网站上找到的教程,我模仿了他们演示的树结构。问题是,我希望文件夹“网站”是一个空文件夹,但 JTree 将它显示为好像它是一个文件。如何告诉 JTree “网站”实际上是一个空文件夹?

更新

我已经开始制作一个简单的“联系人管理器”。我想要做的基本上是使名称看起来像文件夹(因为我想为每个文件夹添加信息),但不添加任何内容。即有些可能没有任何信息,但我仍然希望它们看起来像文件夹。

浏览器类的代码:

import java.awt.Component;
import java.io.File;
import java.util.Iterator;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;


public class Browser extends JFrame implements javax.swing.tree.TreeModel {


    private JTree tree;
    ManagerOfContacts mngrOfContacts;

    public Browser() {

        //Generates the ManagerOfContacts and associated Contacts
        Driver driver = new Driver();
        mngrOfContacts = driver.getManagerOfContacts();
        //---------------------------\\


        DefaultMutableTreeNode contacts = new DefaultMutableTreeNode("Contacts");
        createNodes(contacts);
        tree = new JTree(contacts);

        JScrollPane treeView = new JScrollPane(tree);

        add(treeView);

        setSize(400,400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public void createNodes(DefaultMutableTreeNode top){
        DefaultMutableTreeNode contactName;

        Iterator<Contact> contactItr = mngrOfContacts.getIterator();
        while(contactItr.hasNext()){
            contactName = new DefaultMutableTreeNode(contactItr.next());
            top.add(contactName);
        }
    }

    public static void main(String[] args) {
        Browser browsr = new Browser();
    }

}

【问题讨论】:

  • 您必须“玩”TreeCellRenderer。如果您可以发布一些代码以便我们可以正确指导您,那就太好了。
  • 看看allowsChildren
  • 我应该在哪里寻找“allowsChildren”?
  • 目标是使用任何编程语言(包括 Java)尽可能快速轻松地创建分层文件夹/文档类型树,还是专门使用 Java JTree 来创建?
  • 一开始我也是从Java开始的,后来决定如果树可以在浏览器中实时显示,而不需要任何浏览器插件、插件或扩展,那么它可以用在智能手机、平板电脑或台式机,并且更有用。同时,我认为让任何支持套接字的编程语言都可以使用它会使其更加有用。而且,最终结果就在这里,现在我们正在使用分层结构来创建基于 Web/云的实时应用程序。披露:我为 Accord Software, Inc. (accord.com) 工作

标签: java swing jtree


【解决方案1】:

这就是您创建自己的TreeCellRenderer 的方式,它告诉您的JTree 任何您想要的。由于您使用带有DefaultMutableTreeNode 作为节点的默认树模型,因此您必须提取其用户对象并根据该对象决定要绘制的内容。请注意,默认渲染器只是一个扩展的JLabel,这就是为什么您可以在其中使用setIcon(...)setText(...) 等。

你的叶子节点被文件图标绘制的原因可能是默认渲染器选择基于DefaultMutableTreeNode.getAllowsChildren()的图标,类似于我使用Contact.isSomeProperty()的方式。

import java.awt.Component;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;


public class Browser extends JFrame {


    private JTree tree;
    //ManagerOfContacts mngrOfContacts;

    public Browser() {

        //Generates the ManagerOfContacts and associated Contacts
        //Driver driver = new Driver();
        //mngrOfContacts = driver.getManagerOfContacts();
        //---------------------------\\


        DefaultMutableTreeNode contacts = new DefaultMutableTreeNode("Contacts");
        createNodes(contacts);
        tree = new JTree(contacts);

        // use your own renderer (!)
        tree.setCellRenderer(new MyTreeCellRenderer());

        JScrollPane treeView = new JScrollPane(tree);

        add(treeView);

        setSize(400,400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public final void createNodes(DefaultMutableTreeNode top){
        DefaultMutableTreeNode contactName;

        // dummies
        List<Contact> contacts = new ArrayList<Contact>();
        contacts.add(new Contact("Me", true));
        contacts.add(new Contact("You"));

        Iterator<Contact> contactItr = contacts.iterator();
        while(contactItr.hasNext()){
            contactName = new DefaultMutableTreeNode(contactItr.next());
            top.add(contactName);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Browser browsr = new Browser();
            }
        });

    }

    // dummy
    private static class Contact {

        private boolean someProperty;
        private String name;

        public Contact(String name) {
            this(name, false);
        }

        public Contact(String name, boolean property) {
            this.someProperty = property;
            this.name = name;
        }

        public boolean isSomeProperty() {
            return someProperty;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    // this is what you want
    private static class MyTreeCellRenderer extends DefaultTreeCellRenderer {

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

            // decide what icons you want by examining the node
            if (value instanceof DefaultMutableTreeNode) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
                if (node.getUserObject() instanceof String) {
                    // your root node, since you just put a String as a user obj                    
                    setIcon(UIManager.getIcon("FileView.computerIcon"));
                } else if (node.getUserObject() instanceof Contact) {
                    // decide based on some property of your Contact obj
                    Contact contact = (Contact)  node.getUserObject();
                    if (contact.isSomeProperty()) {
                        setIcon(UIManager.getIcon("FileView.hardDriveIcon"));
                    } else {
                        setIcon(UIManager.getIcon("FileChooser.homeFolderIcon"));
                    }
                }
            }

            return this;
        }

    }
}

这应该可以帮助您入门。您应该在JTree tutorial 中阅读更多相关信息。

【讨论】:

  • 很棒的答案 - 谢谢!你能解释一下你的主要方法SwingUtilities.invokeLater(new Runnable() { public void run() { Browser browsr = new Browser();
  • MyTreeCellRenderer应该在主类里面吗?
  • @Imray 检查此question 以获得第一个问题的答案。您可以像任何其他类一样将渲染器类放在您想要的任何位置。
  • 效果很好!谢谢 :) 顺便说一下,获取可用图标列表: System.out.println("Default icons : "+UIManager.getDefaults());
【解决方案2】:

配置treeModel查询其节点的askAllowsChildren属性,决定是否应将其视为文件夹(即使没有子节点)

DefaultMutableTreeNode root = new DefaultMutableTreeNode("I'm the root");
// node allowsChildren - that's the default 
root.add(new DefaultMutableTreeNode("folder always"));
// node doesn't accept children
root.add(new DefaultMutableTreeNode("folder never", false));
// model configured to query the node's allowsChildren property
DefaultTreeModel model = new DefaultTreeModel(root, true);

【讨论】:

    猜你喜欢
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 2018-03-15
    • 1970-01-01
    • 2012-10-24
    • 2011-05-15
    相关资源
    最近更新 更多