JTree 首次加载时不显示句柄

JTree isn't showing handles when it first loads up

因此,对于我正在处理的项目,我需要来自文件管理器的文件树,它显示系统中的所有目录和文件。我找到了一个名为 FileManager.Java 的完整工作文件管理器,可以在此页面上看到它:https://codereview.stackexchange.com/questions/4446/file-browser-gui

不过,正如我所说,我只需要其中的树部分。我已经实现了这一点,并采用 FileManager.java 代码并将其分解为我认为必要的部分。该代码在这里:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Component;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.filechooser.FileSystemView;

import java.util.List;
import java.io.*;


class FileManager {

    /** Provides nice icons and names for files. */
    private FileSystemView fileSystemView;

    /** File-system tree. Built Lazily */
    private JTree tree;
    private DefaultTreeModel treeModel;

    /** Directory listing */
    private JProgressBar progressBar;

    public Container getGui() {
        fileSystemView = FileSystemView.getFileSystemView();

        // the File tree
        DefaultMutableTreeNode root = new DefaultMutableTreeNode();
        treeModel = new DefaultTreeModel(root);

        TreeSelectionListener treeSelectionListener = new TreeSelectionListener() {
            public void valueChanged(TreeSelectionEvent tse){
                DefaultMutableTreeNode node =
                    (DefaultMutableTreeNode)tse.getPath().getLastPathComponent();
                showChildren(node);
            }
        };

        // show the file system roots.
        File[] roots = fileSystemView.getRoots();
        for (File fileSystemRoot : roots) {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode(fileSystemRoot);
            root.add( node );
            //showChildren(node);
            File[] files = fileSystemView.getFiles(fileSystemRoot, true);
            for (File file : files) {
                if (file.isDirectory()) {
                    node.add(new DefaultMutableTreeNode(file));
                }
            }
        }

        tree = new JTree(treeModel);
        tree.setRootVisible(false);
        tree.addTreeSelectionListener(treeSelectionListener);
        tree.setCellRenderer(new FileTreeCellRenderer());
        tree.expandRow(0);
        tree.setVisibleRowCount(15);

        JPanel simpleOutput = new JPanel(new BorderLayout(3,3));
        progressBar = new JProgressBar();
        simpleOutput.add(progressBar, BorderLayout.EAST);
        progressBar.setVisible(false);

        return tree;
    }

    public void showRootFile() {
        // ensure the main files are displayed
        tree.setSelectionInterval(0,0);
    }




    /** Add the files that are contained within the directory of this node.
    Thanks to Hovercraft Full Of Eels. */
    private void showChildren(final DefaultMutableTreeNode node) {
        tree.setEnabled(false);
        progressBar.setVisible(true);
        progressBar.setIndeterminate(true);

        SwingWorker<Void, File> worker = new SwingWorker<Void, File>() {
            @Override
            public Void doInBackground() {
                File file = (File) node.getUserObject();
                if (file.isDirectory()) {
                    File[] files = fileSystemView.getFiles(file, true); //!!
                    if (node.isLeaf()) {
                        for (File child : files) {
//                            if (child.isDirectory()) {
                                publish(child);
//                           }
                        }
                    }
                }
                return null;
            }

            @Override
            protected void process(List<File> chunks) {
                for (File child : chunks) {
                    node.add(new DefaultMutableTreeNode(child));
                }
            }

            @Override
            protected void done() {
                progressBar.setIndeterminate(false);
                progressBar.setVisible(false);
                tree.setEnabled(true);
            }
        };
        worker.execute();
    }
}


/** A TreeCellRenderer for a File. */
class FileTreeCellRenderer extends DefaultTreeCellRenderer {

    private FileSystemView fileSystemView;

    private JLabel label;

    FileTreeCellRenderer() {
        label = new JLabel();
        //label.setOpaque(true);
        fileSystemView = FileSystemView.getFileSystemView();
    }

    @Override
    public Component getTreeCellRendererComponent(
        JTree tree,
        Object value,
        boolean selected,
        boolean expanded,
        boolean leaf,
        int row,
        boolean hasFocus) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
        File file = (File)node.getUserObject();
        label.setIcon(fileSystemView.getSystemIcon(file));
        label.setText(fileSystemView.getSystemDisplayName(file));
        label.setToolTipText(file.getPath());

        if (selected) {
            label.setBackground(backgroundSelectionColor);
            label.setForeground(textSelectionColor);
        } else {
            label.setBackground(backgroundNonSelectionColor);
            label.setForeground(textNonSelectionColor);
        }

        return label;
    }
}

当我将它调用到我的实际程序中时,一切正常,除了目录的句柄。我不知道如何让它们在程序启动后立即显示。出于某种原因,您必须先单击该目录才能显示它。如果有人有任何想法,那将不胜感激。

如果有帮助,当我将它调用到我的程序中时,我所做的就是

FileManager fm = new FileManager();
JScrollPane fmsp = new JScrollPane(fm.getGUI);

everything works fine, except for the handles for the directories. I can't figure out how to get them to display as soon as the program starts.

有两种方法:

  • 使用depthFirstEnumeration()调用scrollPathToVisible(); assuming DefaultMutableTreeNode, you can obtain a suitable TreePath as shown here

  • 为每个要展开的节点调用expandRow()

    for (int i = 0; i < tree.getRowCount(); i++) {
        tree.expandRow(i);
    }