重新分配JTree后,getLastSelectedPathComponent()返回null

时间:2014-08-22 10:04:06

标签: java swing jtree

我的JFrame中有一个JTree,并使用getLastSelectedPathComponent()来修改select节点的值。在重新分配JTree之后,getLastSelectedPathComponent()返回null。 我重新分配JTree的代码如下:

protected void refreshTree(JScrollPane jsptree) {
    DefaultMutableTreeNode rootNode;
    File rootSaveFile = new File(System.getProperty("user.dir") + "\\doc");
    if (rootSaveFile.exists()) {
        rootNode = new DefaultMutableTreeNode(rootSaveFile.getName());
        createFiles(rootNode, rootSaveFile.listFiles());
    } else {
        rootNode = new DefaultMutableTreeNode("error");
    }
    this.jtree = new JTree(rootNode);

    this.jsptree.updateUI();
    jsptree.setViewportView(jtree);
    jtree.setEditable(true);

}

3 个答案:

答案 0 :(得分:0)

你不应该建立一个新的JTree。你应该更新它的模型。

此外,您可能需要一种算法来恢复扩展/选择状态。

我正在研究类似的东西,我会发布一些代码,但要小心,不要测试。 此代码位于TreeModel实现中。

public void refresh() {
    final TreePath[] selectionPaths = files.getSelectionPaths();
    final Enumeration<TreePath> expandedDescendants = files.getExpandedDescendants(new TreePath(root));
    SwingWorker sw = new SwingWorker() {

        @Override
        protected Object doInBackground() throws Exception {
            //HttpUtils.fetchSrc() returns a TreeNode
            syncModel(root, HttpUtils.fetchSrc()); 
            return null;
        }

        @Override
        public void done() {
            //Expand old paths

            //Select old paths

            files.repaint();
        }
    };
    sw.execute();
}

/**
 * Sync two tree nodes. This should be used when refreshing the files tree model.
 * @param localNode Local node
 * @param remoteNode Remote node
 */
private void syncModel(DirOrFile localNode, DirOrFile remoteNode) {
    // Remove deleted nodes
    for (int i = 0; i < localNode.getChildCount(); i++) {
        DirOrFile currentChild = (DirOrFile) localNode.getChildAt(i);
        // Search the 2nd tree for this child
        DirOrFile corespondent = null;
        for (int j = 0; j < remoteNode.getChildCount(); j++) {
            DirOrFile current = (DirOrFile) remoteNode.getChildAt(j);
            if (current.getUserObject().equals(currentChild.getUserObject())) {
                corespondent = current;
            }
        }
        // Corespondent not found, we need to remove this node from local tree
        if (corespondent == null) {
            localNode.remove(currentChild);
            notifyListeners(localNode); // Fire tree model change event
        } else if (corespondent.isDirectory()){
            // Recurively sync
            syncModel (currentChild, corespondent);
        }
    }

    // Add missing nodes
    for (int i=0; i < remoteNode.getChildCount(); i++) {
        DirOrFile remoteCurrent = (DirOrFile) remoteNode.getChildAt(i);
        // Search the 1st tree node to see if this node should be added.
        DirOrFile corespondent = null;
        for (int j=0; j < localNode.getChildCount(); j++) {
            DirOrFile localCurrent = (DirOrFile) localNode.getChildAt(j);
            if (localCurrent.getUserObject().equals(remoteCurrent.getUserObject())) {
                corespondent = remoteCurrent;
            }
        }
        // If no corespondent was found in local tree, add remote node
        if (corespondent == null) {
            localNode.insert(remoteCurrent, i);
            notifyListeners(localNode); // Fire tree model change event
        }
    }
}

答案 1 :(得分:0)

我刚刚遇到这个问题,读到你遇到同样的问题帮助我解决了这个问题。 这就是我认为正在发生的事情。当您通过将树变量重新分配给新树来“重建”树时,您将原始树交换为完全不同的树,包括侦听器。因此,在销毁旧树并将其替换为旧树之后调用的getLastSelectedComponent()是A)调用旧版本,仍然指向旧版本,基本上不再存在(返回null),或者B)调用新版本,该版本没有在视觉上表示,并且在某处看不见,没有选择(返回null)。 编辑:如果您可以直观地确认您添加的新节点在那里,那么它肯定是A而不是B(假设其中一个是正确的)。如果新树不可见,您将看不到新节点添加到新树中(除非您将其添加到旧树中,然后创建了一个具有相同根的新树)

我不确定哪一个更正确,也许既不代表实际发生的事情,但当我通过使用更新我的树时 model = (DefaultTreeModel) tree.getModel(); model.insertNodeInto(newNode, (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(), 0); 没有将树变量分配给新树,它会按预期开始工作,我相信你会发生同样的事情。

答案 2 :(得分:-1)

只需repaint()revalidate() JTree