2009-08-01 4 views
3

TreeViewに表示する(階層的な)データがたくさんあります(子供のアイテムを含めて20K個以上のアイテムがあります)。私のデータの特有の問題は、ツリービューに表示される各オブジェクトが多くのツリービュー項目に存在することです。TreeViewsの階層的なデータとTreeViewの更新技術

  1. Item_A -> Item_B -> ItemC
  2. Item_B -> Item_C
  3. ItemC

Item_Aは、それが示されているようItem_C含まItem_Bが含まれているとしましょう:私はそれによって意味することは、私はこのような階層が持っているかもしれないということです上記。つまり、私のリストにはItem_BItem_Cの階層も表示されます。ここで、Item_B(名前の変更など)というオブジェクトに何かが発生したとします。その後、もちろん両方のアイテム を更新する必要があります。複雑な階層を持つ数千のアイテムがツリービュー内にあると考えてください。ツリービューを更新するためにどのような戦略を使用しますか?スピードはもちろん、ここでの主な関心事ですが、使いやすさとメンテナンスも簡単です。現在、リスト項目の内部マッピングをオブジェクトに保持し、逆もまた同様に項目を見つけて更新します。それは正しい戦略ですか?各更新の後にリストを再作成することで、たくさんのコードを投げ捨てることができますが、どのアイテムパスが展開されたか、折りたたまれているのか分かりません。どうすればこの問題を解決できますか?拡張されたパスを内部コンテナに格納する必要がありますか?

ありがとうございます。

PS:プログラミング言語はC++、GUIライブラリはQT3です。

答えて

1

私はTreeView共通コントロールを使用して、長い時間前に何かしました。

私がしたことは、CUSTOMDRAWフラグを設定し、それぞれの可能な異なるノードの単一のインスタンスを保持し、各ノードがこのインスタンスを指し示すようにしました:3つのItem_Cノードはそれぞれ、同じユニークなItem_Cインスタンスへのポインタを持ちます。

したがって、Item_Cのデータを変更すると、(単一の)変更されたデータに対して行われた変更を反映するために、3つのItem_CノードでInvalidateRect()を呼び出すだけでした。

ここでも同じ戦略を適用できると思います。

1

プロジェクトでQt4を使用できる場合は、Qt4モデル/ビューを使用してください。

あなたがそうしたことがないのであれば面倒な作業をすることができますが、一度セットアップすると、同じオブジェクトの複数のインスタンスを簡単に参照/更新できます。選択/複数の選択も処理できます。

は、私は(与えられたモデル/ビュー/コントローラのデザインパターンはかなり古いです)Qtのモデル/ビューの実装の大ファンではないが、それはすべて編集し、

1

無効に更新がwidget->setUpdatesEnabled(false)を使用したGUIでデータを整理するのに役立ちますあなたはそれをwidget->setUpdatesEnabled(true)でレンダリングすることができます。

Qt documentationを参照してください。

1

wxWidgetsツリーコントロールを使用して同様の問題を解決しました。私はコントロールに入れていたオブジェクトを追跡するためにシングルトンリファレンスカウンタを使用し、それらをトラバースするイテレータを使用しました。ここに例があります。

class ReferenceCounter 
{ 
public: 
    // Singleton pattern. Implementation left up to you. 
    static ReferenceCounter& get(); 

    void add(const TreeData& data) { 
     mCounter[data.getId()].push_back(&data); 
    } 

    void remove(const TreeData& data) { 
     const CounterType::const_iterator itr = mCounter.find(data.getId()); 
     if (itr != mCounter.end()) { 
      ItemType& items = itr->second; 
      items.erase(std::remove(items.begin(), items.end(), &data), items.end()); 
      if (items.empty()) { 
       mCounter.erase(itr); 
      } 
     } 
    } 

    typedef std::vector<TreeData*> ItemType; 
    ItemType::iterator begin(const TreeData& data) { 
     const CounterType::const_iterator itr = mCounter.find(data.getId()); 
     if (itr != mCounter.end()) { 
      return itr->second.begin(); 
     } 
     // Else condition handling left up to you. 
    } 

    ItemType::iterator end(const TreeData& data) { 
     const CounterType::const_iterator itr = mCounter.find(data.getId()); 
     if (itr != mCounter.end()) { 
      return itr->second.end(); 
     } 
     // Else condition handling left up to you. 
    } 

private:  
    typedef std::map<int, ItemType> CounterType; 
    CounterType mCounter; 
}; 

class TreeData 
{ 
public: 
    TreeData() { ReferenceCounter::get().add(*this); } 
    ~TreeData() { ReferenceCounter::get().remove(*this); } 

    // Get database rows or whatever your tree is tracking. 
    int getId() const; 
}; 

したがって、任意のTreeDataを指定すると、参照カウンタ内の一致するidsを持つ他のすべてのTreeDataを検索できます。これにより、名前と物事を最新の状態に保ちながら、簡単かつ迅速に行うことができます。私たちのツリーは問題なく1,000,000以上のノードを処理します。私の実装では、より簡単に使用できるように、反復処理をboost::iterator_facadeクラスにラップしました。

関連する問題