【问题标题】:Problems updating JTree changes with JButton使用 JButton 更新 JTree 更改时出现问题
【发布时间】:2013-12-17 02:03:38
【问题描述】:

我在一个有几个人的项目中,我的任务是编译一个可以工作的 JTree 来显示一个集合目录的结构。事实上,JTree 在类开始时显示文件和文件夹的正确结构。但是,我似乎无法让它能够在添加或减去文件时更新(不是使用 JTree)。在我快乐的无知中(非常反对那个),我添加了一个 JButton;

treeModel.reload();

...并希望这能解决问题。它确实重新加载了 JTree,但没有更改文件结构,即使在加载类之后添加了几个文件。

因此,我相信这个社区会指出我的问题的根源,以及语义和逻辑方面的其他缺陷。我是一个愿意学习的人。

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

【问题讨论】:

  • 我认为您必须在新的文件结构上重新创建模型,否则会再次显示相同的树,然后将其传递给 JTree

标签: java swing jbutton jtree


【解决方案1】:
treeModel.reload();

我猜你需要调用而不是仅仅调用上面的代码:

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

重新创建 TreeModel 以反映新的目录结构。

【讨论】:

  • 调用 createTree() 没有区别,treeModel = new DefaultTreeModel() 也没有。我有这种恼人的感觉,我忽略了一些非常基本的东西:/
  • @quidproquo,是的,在创建新的 TreeModel 之后,您需要将模型添加到树中。请参阅上面的新代码。
  • 谢谢,确实做到了。我不知道你可以这样设置模型。我对您的解决方案的简单性感到非常满意。
【解决方案2】:

DefaultTreeModel#reload 基本上说明...

如果您修改了此方法所在的 TreeNode,请调用此方法 型号取决于。该模型将通知其所有侦听器 给定节点下方的模型已更改。

这假设模型本身已经改变。

你至少有两个基本的行动方案...

你可以...

  • 创建一个新的DefaultTreeModel
  • 从现有DefaultTreeModel中删除所有节点...

然后重新构建模型。

如果您创建新的TreeModel,请确保将其设置为与JTree 相对应。

这有点笨拙,但即使您选择编写填充算法以检查模型的现有内容,您仍然需要遍历文件结构。

更新模型可以让您保留JTree 的一些状态(例如,哪些节点被扩展或不扩展)

如果您有幸使用 Java 7,您还可以利用 File Watcher API,例如,您可以将每个目录节点设置为观察者服务,以监控其自己的内容和发生更改时更新自身(添加/删除节点)。

看看Watching a Directory for Changes

【讨论】:

  • 'Watching a Directory for Changes' 的链接是黄金,它有点超出了这个任务的限制,但它确实提供了一种非常动态的方式来检测目录中的变化。另外,我怀疑你关于创建新 TreeModel 的建议是正确的。
猜你喜欢
  • 2022-08-13
  • 1970-01-01
  • 2021-02-09
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多