2017-02-24 9 views
0

나는 JTree을 사용하는 스윙 응용 프로그램을 가지고 있습니다. 트리의 노드 중 일부를 숨기고 싶습니다. 그래서 두 개의 노드를 구현했습니다. 하나는 모든 노드와 하나는 필터링 된 것으로 표시해야합니다. 후자는 실제 모델로 설정됩니다.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] 또는 [Short, Self Contained, Correct Example] (http://www.sscce.org/)를 게시하십시오. 2) * "JTree를 확장하는 커스텀 클래스"* "JTree를 확장하는 경우가 아닌 ** 100 대 1의 확률을 부여합니다. –

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