JTree如何显示文件名?

3
在我的项目中,我正在尝试添加一个文件浏览器,以便用户可以从给定目录中选择文件。我想将此视图限制为项目的根文件夹(由用户确定)。这非常类似于Eclipse的包资源管理器,因为“工作区”是由用户确定的。
目前,文件不显示完整路径(来自C :),这正是我想要的,但所有文件夹都显示完整路径(我不想要,我只想要文件夹名称)。
那么JTree是如何显示这些名称的呢?
我看到JTree使用File.toString()方法,但是当我实现了自己的文件并重写了toString方法时,什么也没有改变。
下面是我的代码:
import java.awt.BorderLayout;
import java.io.File;

import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.util.Collections;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;

public class pnl_fileView extends JPanel {
    /**
     * Display a file system in a JTree view
     * 
     * @version $Id: FileTree.java,v 1.9 2004/02/23 03:39:22 ian Exp $
     * @author Ian Darwin
     */
    /** Construct a FileTree */

    //  public pnl_fileView(){
    private myFile projectFile;
    public pnl_fileView(myFile dir) {
        //Create file explorer
        //Need to add setup for root folder change.
        //Config.getProject(); //This gets the current file from the config file.
        //Begin choose File
        if(projectFile == null){
            JFileChooser chooser;
            String choosertitle = "Please Choose a Root Folder";
            chooser = new JFileChooser(); 
            chooser.setCurrentDirectory(new java.io.File("."));
            chooser.setDialogTitle(choosertitle);
            chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            //
            // disable the "All files" option.
            //
            chooser.setAcceptAllFileFilterUsed(false);
            //    
            if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { 
                System.out.println("getCurrentDirectory(): " + chooser.getCurrentDirectory());
                System.out.println("getSelectedFile() : " + chooser.getSelectedFile());
                projectFile = new myFile(chooser.getSelectedFile().getAbsolutePath());
                //projectFile = chooser.getSelectedFile();
            }
            else {
                System.out.println("No Selection ");
            }
        }
        else {
            // Figure out where in the filesystem to start displaying
        }

        //End choose file
        setLayout(new BorderLayout());

        // Make a tree list with all the nodes, and make it a JTree
        JTree tree = new JTree(addNodes(null, projectFile));

        // Add a listener
        tree.addTreeSelectionListener(new TreeSelectionListener() {
            public void valueChanged(TreeSelectionEvent e) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) e
                        .getPath().getLastPathComponent();
                System.out.println("You selected " + node);
            }
        });

        // Lastly, put the JTree into a JScrollPane.
        JScrollPane scrollpane = new JScrollPane();
        scrollpane.getViewport().add(tree);
        add(BorderLayout.CENTER, scrollpane);
    }

    /** Add nodes from under "dir" into curTop. Highly recursive. */
    DefaultMutableTreeNode addNodes(DefaultMutableTreeNode curTop, myFile dir) {
        String curPath = dir.getPath();
        System.out.println(curPath);
        DefaultMutableTreeNode curDir = new DefaultMutableTreeNode(curPath);
        if (curTop != null) { // should only be null at root
            curTop.add(curDir);
        }
        Vector<String> ol = new Vector<String>();
        String[] tmp = dir.list();
        for (int i = 0; i < tmp.length; i++)
            ol.addElement(tmp[i]);
        Collections.sort(ol, String.CASE_INSENSITIVE_ORDER);
        myFile f;
        Vector<String> files = new Vector<String>();
        // Make two passes, one for Dirs and one for Files. This is #1.
        for (int i = 0; i < ol.size(); i++) {
            String thisObject = (String) ol.elementAt(i);
            String newPath;
            if (curPath.equals("."))
                newPath = thisObject;
            else
                newPath = curPath + myFile.separator + thisObject;
            System.out.println("this is the path: " + newPath);
            if ((f = new myFile(newPath)).isDirectory())
                addNodes(curDir, f);
            else
                files.addElement(thisObject);
        }
        // Pass two: for files.
        for (int fnum = 0; fnum < files.size(); fnum++)
            curDir.add(new DefaultMutableTreeNode(files.elementAt(fnum)));
        return curDir;
    }

    public Dimension getMinimumSize() {
        return new Dimension(200, 400);
    }

    public Dimension getPreferredSize() {
        return new Dimension(200, 400);
    }

    /** Main: make a Frame, add a FileTree */
    public static void main(String[] av) {

        JFrame frame = new JFrame("FileTree");
        frame.setForeground(Color.black);
        frame.setBackground(Color.lightGray);
        Container cp = frame.getContentPane();

        if (av.length == 0) {
            cp.add(new pnl_fileView(new myFile(".")));
        } else {
            cp.setLayout(new BoxLayout(cp, BoxLayout.X_AXIS));
            for (int i = 0; i < av.length; i++)
                cp.add(new pnl_fileView(new myFile(av[i])));
        }

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
class myFile extends File{
    public myFile(String pathname) {
        super(pathname);

    }
    public String toString() {
        return "Hello World!";
    }
    public String getAbsolutePath(){
        return "hi";
    }
}

1
取决于情况。JTree 将使用 Object#toString 来确定每个节点应该显示什么。您应该创建自己的 TreeCellRenderer,以便确定最佳的显示对象方式。如果您能提供一个可工作的示例,那么帮助您会更容易些。 - MadProgrammer
添加了我的代码,我查看了treeCellRenderer,但是在使其正常工作方面遇到了一些问题。代码的基础来自另一个来源,因此仍然有一些未删除的片段。 - Jeff B
请学习Java命名规范并遵守它们。 - kleopatra
2个回答

5

4
个人而言,我不会尝试使用其他对象来设置节点的显示值,而是将其留给TreeCellRenderer决定。这样做的主要原因是,节点包含的数据可能需要被程序的其他部分使用。

enter image description here

import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;

public class TestFileTree extends JPanel {

    private File projectFile;

    public TestFileTree(File dir) {
        //Create file explorer
        //Need to add setup for root folder change.
        //Config.getProject(); //This gets the current file from the config file.
        //Begin choose File
        if (projectFile == null) {
            JFileChooser chooser;
            String choosertitle = "Please Choose a Root Folder";
            chooser = new JFileChooser();
            chooser.setCurrentDirectory(new java.io.File("."));
            chooser.setDialogTitle(choosertitle);
            chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            //
            // disable the "All files" option.
            //
            chooser.setAcceptAllFileFilterUsed(false);
            //    
            if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
                System.out.println("getCurrentDirectory(): " + chooser.getCurrentDirectory());
                System.out.println("getSelectedFile() : " + chooser.getSelectedFile());
                projectFile = new File(chooser.getSelectedFile().getAbsolutePath());
                //projectFile = chooser.getSelectedFile();
            } else {
                System.out.println("No Selection ");
            }
        } else {
            // Figure out where in the filesystem to start displaying
        }

        //End choose file
        setLayout(new BorderLayout());

        // Make a tree list with all the nodes, and make it a JTree
        JTree tree = new JTree(addNodes(null, projectFile));
        tree.setCellRenderer(new MyTreeCellRenderer());

        // Add a listener
        tree.addTreeSelectionListener(new TreeSelectionListener() {
            public void valueChanged(TreeSelectionEvent e) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) e
                        .getPath().getLastPathComponent();
                System.out.println("You selected " + node);
            }
        });

        // Lastly, put the JTree into a JScrollPane.
        JScrollPane scrollpane = new JScrollPane();
        scrollpane.getViewport().add(tree);
        add(BorderLayout.CENTER, scrollpane);
    }

    /**
     * Add nodes from under "dir" into curTop. Highly recursive.
     */
    DefaultMutableTreeNode addNodes(DefaultMutableTreeNode curTop, File dir) {
        DefaultMutableTreeNode curDir = new DefaultMutableTreeNode(dir);
        if (curTop != null) { // should only be null at root
            curTop.add(curDir);
        }
        File[] tmp = dir.listFiles();
        Vector<File> ol = new Vector<File>();
        ol.addAll(Arrays.asList(tmp));
        Collections.sort(ol, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {

                int result = o1.getName().compareTo(o2.getName());

                if (o1.isDirectory() && o2.isFile()) {
                    result = -1;
                } else if (o2.isDirectory() && o1.isFile()) {
                    result = 1;
                }

                return result;
            }
        });
        // Pass two: for files.
        for (int fnum = 0; fnum < ol.size(); fnum++) {
            File file = ol.elementAt(fnum);
            DefaultMutableTreeNode node = new DefaultMutableTreeNode(file);
            if (file.isDirectory()) {
                addNodes(node, file);
            }
            curDir.add(node);
        }
        return curDir;
    }

    public Dimension getMinimumSize() {
        return new Dimension(200, 400);
    }

    public Dimension getPreferredSize() {
        return new Dimension(200, 400);
    }

    public static void main(String[] av) {

        JFrame frame = new JFrame("FileTree");
        frame.setForeground(Color.black);
        frame.setBackground(Color.lightGray);
        Container cp = frame.getContentPane();

        if (av.length == 0) {
            cp.add(new TestFileTree(new File(".")));
        } else {
            cp.setLayout(new BoxLayout(cp, BoxLayout.X_AXIS));
            for (int i = 0; i < av.length; i++) {
                cp.add(new TestFileTree(new File(av[i])));
            }
        }

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public class MyTreeCellRenderer extends DefaultTreeCellRenderer {

        private FileSystemView fsv = FileSystemView.getFileSystemView();

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
            System.out.println(value);
            super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
            if (value instanceof DefaultMutableTreeNode) {
                value = ((DefaultMutableTreeNode)value).getUserObject();
                if (value instanceof File) {
                    File file = (File) value;
                    if (file.isFile()) {
                        setIcon(fsv.getSystemIcon(file));
                        setText(file.getPath());
                    } else {
                        setIcon(fsv.getSystemIcon(file));
                        setText(file.getName());
                    }
                }
            }
            return this;
        }
    }
}

您的代码有些“有趣”的地方。
尽管`Vector`并不是一个坏选择,但`List`(或在这种情况下,特别是`ArrayList`)更快,因为它没有同步机制。
您可以使用`Arrays.asList(...)`将数组转换为列表,并使用`List#addAll`方法(也在`Vector`中),而不是使用循环来添加元素到列表中。
我不确定您使用的Java版本是什么,但自Java 6以来(我认为),您现在可以使用`for-each`,这意味着您可以替换`for (int i = 0; i < ol.size(); i++)`为`for (String thisObject : ol)`。
由于您在列表中使用了泛型,因此无需强制转换对象 ;)

1
fsv.getSystemIcon(file) 注意使用本地PLAF效果更佳。请参见trashgod的答案中的链接FileBrowserGui以获取屏幕截图。 - Andrew Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接