2017-02-24 63 views
0

我有一個使用JTree的Swing應用程序。我希望樹的某些節點被隱藏,所以我實現了兩個DefaultTreeModel,每個節點都有一個節點,並且只有那些應該顯示的節點。後者被設定爲實際模型。爲什麼TreeModel重新加載後節點選擇無法正常工作?

在某些點上,我必須更改過濾的節點,當我這樣做時,樹中的項目會正確更新,但它們的行爲是錯誤的。 節點在被選中時不會突出顯示(即使它們確實被選中),並且用戶不能再雙擊來展開節點,但它們必須單擊小小的「+」按鈕。

下面是我的代碼的概括,我的自定義類中的兩個方法擴展了JTree

updateFilter當過濾器需要更新時被調用。 populateFilteredNode以遞歸方式填充我過濾模型的根節點。爲簡單起見,filteredRoot是一個類成員變量(類型爲DefaultMutableTreeNode),並且是過濾模型的根。 fullModelfilteredModel的類型DefaultTreeModel

public void updateFilter() { 
    // Get current expansion state 
    ArrayList<Integer> expansionState = getExpansionState(); 

    DefaultMutableTreeNode fullModelRoot = fullModel.getRoot(); 

    // Remove existing nodes in the filtered model 
    while(filteredRoot.getChildCount() > 0) { 
     filteredModel.removeNodeFromParent(filteredRoot.getFirstChild()); 
    } 

    populateFilteredNode(fullModelRoot, filteredRoot); 

    // Repaint tree and restore expansion state 
    repaint(); 
    setExpansionState(expansionState); 
} 

private void populateFilteredNode(DefaultMutableTreeNode fullNode, DefaultMutableTreeNode filteredNode) { 

    int index = 0; 

    for(int n = 0; n < fullNode.getChildCount(); n++) { 
     DefaultMutableTreeNode fullChildNode = fullNode.getChildAt(n); 

     // Show the item and its children if one of many cases is true 
     if(shouldShowItem(fullChildNode.getItem())) { 
      DefaultMutableTreeNode filteredChildNode = fullChildNode.clone(); 

      filteredModel.insertNodeInto(filteredChildNode, filteredNode, index++); 

      populateFilteredNode(fullChildNode, filteredChildNode); 
     } 
    } 
} 

如果任何人有類似的經歷或知道爲什麼選定的節點將不會高亮顯示,請讓我知道的。或者如果有更好的方法來完成過濾。或者如果更多的代碼可以幫助提供答案。

+0

1)爲了更好地提供幫助,請發佈[MCVE]或[簡短,獨立,正確的示例](http://www.sscce.org/)。 2)*「..我自定義的類擴展了'JTree'。」*我會給出100比1的賠率,這是**不是**擴展'JTree'的情況。 –

+0

@Andrew我承認我是新手,所以我不知道我應該或不應該創建自定義子類。爲什麼你會打賭,這不是擴展'JTree'的情況?這是否與所選節點爲什麼不突出有關? – Robin

+0

當我查看代碼時,我會知道更多。有一個MCVE/SSCCE後,我會查看代碼。 –

回答

0

我發現了一些適用於我的情況的東西,雖然它很快且很髒,我不一定明白它爲什麼起作用。 Code Ranch上的This 12-year-old post以某種方式讓我朝着正確的方向前進。我只是在這裏發佈它,以防任何人有類似的問題,它可能會有所幫助。

在對錶模型進行任何更改之前,我保存選擇路徑,然後在做出更改後調用此新函數findNewSelectionPath。下面是這個函數的一個通用版本(我使用了幾個自定義類,所以我盡了最大努力使它看起來一般可用)。

private TreePath findNewSelectionPath(TreePath oldSelectionPath) { 
    TreePath newSelectionPath = null; 

    if(oldSelectionPath != null) { 
     Object[] oldPathComponents = oldSelectionPath.getPath(); 
     Object[] newPathComponents = new Object[oldPathComponents.length]; 

     DefaultMutableTreeNode node = (DefaultMutableTreeNode) filteredModel.getRoot(); 

     // Set the root 
     if(oldPathComponents[0].equals(node)) { 
      newPathComponents[0] = node; 
     } 

     // Set the rest of the path components 
     for(int n = 1; n < oldPathComponents.length; n++) { 
      for(int k = 0; k < node.getChildCount(); k++) { 
       if(oldPathComponents[n].equals(node.getChildAt(k))) { 
        newPathComponents[n] = node.getChildAt(k); 
        node = node.getChildAt(k); 
        break; 
       } 
      } 
     } 

     // Make sure that the last path component exists 
     if(newPathComponents[newPathComponents.length - 1] != null) { 
      newSelectionPath = new TreePath(newPathComponents); 
     } 
    } 
    return newSelectionPath; 
}