2017-02-24 7 views
0

私はJTreeを使用するSwingアプリケーションを持っています。私はツリーのいくつかのノードを隠しておきたいので、2つのノードを実装しました.1つはすべてのノードに、もう1つは表示するものだけでフィルタリングしました。後者は実際のモデルとして設定されています。TreeModelのリロード後にノード選択が正しく機能しないのはなぜですか?

フィルタリングされたノードを変更する必要がありますが、ツリーのアイテムは正しく更新されますが、その動作は間違っています。 ノードが選択されても強調表示されず(実際に選択されているにもかかわらず)、ユーザはダブルクリックしてノードを展開することはできません。少しの「+」ボタンをクリックする必要があります。

以下は私のコードの一般化です。私のカスタムクラスの2つのメソッドはJTreeです。

updateFilterは、フィルタを更新する必要があるときに呼び出されます。 populateFilteredNodeは、フィルタされたモデルのルートノードを再帰的に設定します。簡単にするため、filteredRootはクラスメンバ変数(タイプDefaultMutableTreeNode)であり、フィルタ処理されたモデルのルートです。誰もが似たような経験を持っているか、選択したノードがハイライトされ表示されない理由を知っている場合はfullModelfilteredModelDefaultTreeModel

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を拡張する私のカスタムクラス" *これは、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; 
} 
関連する問題