简体   繁体   English

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

[英]After re-assign the JTree,getLastSelectedPathComponent() returns null

I have a JTree in my JFrame and use getLastSelectedPathComponent() to modify the value of select node. 我的JFrame中有一个JTree,并使用getLastSelectedPathComponent()修改选择节点的值。 After I re-assign the JTree, the getLastSelectedPathComponent() returns null. 在我重新分配JTree之后,getLastSelectedPathComponent()返回null。 The code that I re-assign the JTree as follows: 我重新分配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);

}

You should not build a new JTree. 您不应构建新的JTree。 You should update it's model instead. 您应该改为更新它的模型。

Also it's possible you need an algorithm to restore expansion/selected state. 另外,您可能需要一种算法来还原扩展/选定状态。

I am working on something similar, I'll post some code, but careful, IT'S NOT TESTED. 我正在做类似的事情,我会发布一些代码,但是要小心,它没有经过测试。 This code is inside a TreeModel implementation. 这段代码在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
        }
    }
}

I just encountered this problem, and reading you encountering the same issue helped me fix it. 我刚遇到此问题,而阅读您遇到的同一问题有助于我解决此问题。 Here's what I think is happening. 我认为这是正在发生的事情。 When you "rebuild" the tree by reassigning the tree variable to a new tree, you're swapping the original tree for an entirely different tree, including the listeners . 通过将tree变量重新分配给新树来“重建”树时,您会将原始树交换为完全不同的树, 包括listeners So the getLastSelectedComponent() you call after destroying the old tree and replacing it with the old one is either A) calling the old version, still pointing to the old tree, which basically doesn't exist anymore(returning null), or B) calling the new version, which is not being visually represented, and is sitting, invisible somewhere, with nothing selected(returning null). 因此,在销毁旧树并将其替换为旧树后调用的getLastSelectedComponent()是A)调用旧版本,仍然指向基本上不再存在的旧树(返回null),或B)调用新版本,该新版本未在视觉上表示出来,而是坐着,在某处不可见,没有选择任何内容(返回null)。 EDIT: If you can visually confirm that the new node that you added is there, then it's definitely A rather than B (assuming one of the two is correct). 编辑:如果您可以直观地确认添加的新节点在那,那么它肯定是A而不是B(假设两者之一是正确的)。 Were the new tree invisible, you wouldn't see the new node added to the new tree(unless you added it to the old tree, and then created a new one with the same root) 如果新树不可见,您将看不到新节点添加到新树中(除非您将其添加到旧树中, 然后使用相同的根创建了新树)

I'm not sure which of these is more correct, maybe neither represents what's actually going on, but when I update my tree by using model = (DefaultTreeModel) tree.getModel(); model.insertNodeInto(newNode, (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(), 0); 我不确定其中哪个更正确,也许都不代表实际情况,但是当我通过使用model = (DefaultTreeModel) tree.getModel(); model.insertNodeInto(newNode, (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(), 0);更新树时model = (DefaultTreeModel) tree.getModel(); model.insertNodeInto(newNode, (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(), 0); model = (DefaultTreeModel) tree.getModel(); model.insertNodeInto(newNode, (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(), 0); WITHOUT assigning the tree variable to a new tree, it starts working as expected, and I'm sure that the same will happen for you. 如果不将tree变量分配给新树,它就会按预期开始工作,并且我相信您也会遇到同样的情况。

只需repaint()revalidate() JTree

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM