2

So for a project I'm working on, I need the file tree from a file manager that displays all of the directories and files from a system. I found a full working file manager called FileManager.Java which can be seen on this page: https://codereview.stackexchange.com/questions/4446/file-browser-gui

However, as I said, I only need the tree part of this. I have already achieved this, and took the FileManager.java code and broke it down to what I believed necessary. That code is here:

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;
    }
}

When I call this into my actual program, 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. For some reason, you have to click on the directory first in order for it to show up. If anyone has any ideas, that'd be greatly appreciated.

If it helps, when I call this into my program, all I do is

FileManager fm = new FileManager();
JScrollPane fmsp = new JScrollPane(fm.getGUI);
Community
  • 1
  • 1
MCLight1
  • 23
  • 2
  • 1
    I'd recommend you adjust your sample so it includes a `main()` method, allowing us to copy/paste/reproduce. Please also ensure it's as minimal as possible. – Duncan Jones Mar 09 '15 at 14:37
  • 1
    It appears that the file sub-tree for each node is created lazily by design, as stated in the code comments `/* GUI options/containers for new File/Directory creation. Created lazily. */` The trigger for that creation is a `TreeSelectionEvent` which requires that you most first click a node in the tree before its sub-tree is created. – dbank Mar 09 '15 at 15:22

1 Answers1

1

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.

Two approaches suggest themselves:

  • Invoke scrollPathToVisible(); assuming DefaultMutableTreeNode, you can obtain a suitable TreePath as shown here using depthFirstEnumeration().

  • Invoke expandRow() for each node you want expanded:

    for (int i = 0; i < tree.getRowCount(); i++) {
        tree.expandRow(i);
    }
    
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045