[英]After re-assign the JTree,getLastSelectedPathComponent() returns null
我的JFrame中有一个JTree,并使用getLastSelectedPathComponent()修改选择节点的值。 在我重新分配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);
}
您不应构建新的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
}
}
}
我刚遇到此问题,而阅读您遇到的同一问题有助于我解决此问题。 我认为这是正在发生的事情。 通过将tree变量重新分配给新树来“重建”树时,您会将原始树交换为完全不同的树, 包括listeners 。 因此,在销毁旧树并将其替换为旧树后调用的getLastSelectedComponent()是A)调用旧版本,仍然指向基本上不再存在的旧树(返回null),或B)调用新版本,该新版本未在视觉上表示出来,而是坐着,在某处不可见,没有选择任何内容(返回null)。
编辑:如果您可以直观地确认添加的新节点在那,那么它肯定是A而不是B(假设两者之一是正确的)。 如果新树不可见,您将看不到新节点添加到新树中(除非您将其添加到旧树中, 然后使用相同的根创建了新树)
我不确定其中哪个更正确,也许都不代表实际情况,但是当我通过使用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);
如果不将tree变量分配给新树,它就会按预期开始工作,并且我相信您也会遇到同样的情况。
只需repaint()
和revalidate()
JTree
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.