문제

I'm on a project with several people, and my task is to compile a working JTree to show the structure of a set directory. As it is, the JTree shows the correct structure of files and folders when the class starts. However, I can't seem to get it to be able to update when files are added or subtracted (not with the JTree). In my happy ignorance (quite presistant that one) I added a JButton with;

treeModel.reload();

...and hoped that would do the trick. It reloaded the JTree sure enough, but didn't change the file structure, even though several files were added after the class loaded.

And it is thus I place my trust in this community to both point out the source of my issues, and other lackings in semantics and logic. I'm a willing learner.

    public class FileTree extends JPanel {

    private JTree tree;
    private DefaultMutableTreeNode root;
    private DefaultTreeModel treeModel;

    public FileTree(JPanel jp) {
        jp.setLayout(new BorderLayout());

        final File directory = getDir();
        createTree(directory);

        tree = new JTree(treeModel);
        tree.setRootVisible(true);
        tree.setShowsRootHandles(true);
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        tree.setCellRenderer(new FileTreeCellRenderer());
        tree.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                 TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
                 if(e.getClickCount() == 2) {
                    Object n        = selPath.getLastPathComponent();
                    String sel      = n.toString();
                    File nodeFile   = new File(sel);

                    if(nodeFile.isDirectory() && (!nodeFile.isHidden())) {
                        UserWindow.printToLog("doubble-click event on folder: " + nodeFile.getName());
                        //TODO:stuff happening here
                    }

                     if(nodeFile.isFile() && (!nodeFile.isHidden())) {
                         UserWindow.printToLog("doubble-click event on file: " + nodeFile.getName());
                         new FileTreeEventHandler(nodeFile);
                     }
                 } 
            }
        });
        JScrollPane sp = new JScrollPane(tree);
        jp.add(sp);
        JButton updateButton = new JButton("Update");
        updateButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                treeModel.reload();
            }
        });
        jp.add(updateButton, BorderLayout.SOUTH);
        setVisible(true);
    }

    private void createTree(File directory) {
        root = new DefaultMutableTreeNode();
        treeModel = new DefaultTreeModel(root);
        DefaultMutableTreeNode node = new DefaultMutableTreeNode(directory);

        root.add(node);
        populate(directory, node);
    }

    private void populate(File directory, DefaultMutableTreeNode node) {
        String[] files = directory.list();
        for(String file : files) {
            File currentFile = new File(directory, file);
            addLeaf(node, currentFile);
        }
    }

    private void addLeaf(DefaultMutableTreeNode node, File currentFile) {
        if(currentFile.isFile() && !currentFile.isHidden()) {
            DefaultMutableTreeNode leafFile = new DefaultMutableTreeNode(currentFile);
            node.add(leafFile);
        }
        if(currentFile.isDirectory() && !currentFile.isHidden()) {
            DefaultMutableTreeNode folder = new DefaultMutableTreeNode(currentFile);
            node.add(folder);
            populate(currentFile, folder);
        }
    }

    private File getDir() {
        String path = new File(System.getProperty("user.dir"), "downloaded content").getAbsolutePath();
        File dir = new File(path);
        if(!dir.exists()) {
            dir.mkdirs();
        }
        return dir;
    }       
}
도움이 되었습니까?

해결책

treeModel.reload();

Instead of just invoking the above code, I would guess you need to invoke:

createTree(directory);
tree.setModel(treeModel);

to recreate the TreeModel to reflect the new directory structure.

다른 팁

DefaultTreeModel#reload basically states...

Invoke this method if you've modified the TreeNodes upon which this model depends. The model will notify all of its listeners that the model has changed below the given node.

This assumes that the model itself has changed.

You have at least two basic course of actions...

You could...

  • Create a new DefaultTreeModel or
  • Remove all the nodes from the existing DefaultTreeModel...

And then re-build the model.

If you create a new TreeModel, make sure you set it against the JTree.

This is a little heavy handed, but even if you choose to write the population algorithm so that it checked the existing content of the model, you're still going to have to walk the file structure.

Updating the model could allow you to preserve some of the state of the JTree (ie what nodes are expanded or not, for example)

If you're lucky enough to be using Java 7, you could also take advantage of the File Watcher API, which would allow you to, for example, set each directory node up as a watcher service to monitor it's own content and update itself (add/remove nodes) when changes occur.

Take a look at Watching a Directory for Changes

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top