3

TreeView に表示する (階層的な) データがたくさんあります (子アイテムを含めて、約 20,000 個以上のアイテムになる可能性があります)。私のデータの特有の問題は、ツリービューに表示される各オブジェクトが多くのツリービュー項目に存在できることです。つまり、次のような階層がある可能性があります。

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

上記のように、Item_A含むItem_Bが含むと仮定しましょう。Item_Cこれは、リストに と の階層も表示されることを意味しItem_BますItem_C。次のように示されているオブジェクトに何かが起こったとします。Item_B(例: 名前の変更)。もちろん、両方のアイテムを更新する必要があります。複雑な階層を持つツリービュー内の何千ものアイテムを考えてみましょう。ツリービューを更新するには、どのような戦略を使用しますか? ここではもちろん速度が主な関心事ですが、使いやすさとメンテナンスのしやすさも重要です。現在、アイテムをすばやく見つけて更新するために、リスト アイテムからオブジェクトへの内部マッピング、およびその逆の内部マッピングを保持しています。それは正しい戦略ですか?更新のたびにリストを再作成することで、多くのコードを捨てることができますが、どのアイテム パスが展開または折りたたまれているかはわかりません。どうすればこの問題を解決できますか? 展開されたパスを内部コンテナーに保存する必要がありますか?

ありがとうございました。

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

4

4 に答える 4

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 を指定すると、参照カウンターで ID が一致する他のすべての TreeData を検索できます。これにより、名前などを最新の状態に簡単かつ迅速に維持できます。私たちのツリーは、1,000,000 を超えるノードを問題なく処理します。私の実装では、boost::iterator_facade使いやすいように反復処理をクラスにまとめました。

于 2009-12-15T02:18:08.183 に答える
1

を使用して更新を無効にしwidget->setUpdatesEnabled(false)、必要なすべてを編集してから、 で再有効化しwidget->setUpdatesEnabled(true)ます。

Qt のドキュメントを参照してください。

于 2009-09-09T11:20:42.183 に答える
1

私はずっと前に、Windows TreeView コモン コントロールを使用して同様のことを行いました。

私がしたことは、CUSTOMDRAW フラグを設定し、考えられるそれぞれの異なるノードの 1 つのインスタンスを保持し、各ノードがこのインスタンスを指すようにすることでした。3 つの Item_C ノードはそれぞれ、同じ一意の Item_C インスタンスへのポインターを持ちます。

そのため、Item_C のデータを変更するときは、3 つの Item_C ノードで InvalidateRect() を呼び出して、(単一の) 変更されたデータに加えられた変更を反映するだけで済みました。

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

于 2009-08-05T04:39:03.160 に答える
1

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

独自のモデルを作成する必要がありますが、作成したことがない場合は面倒ですが、セットアップが完了すると、同じオブジェクトの複数のインスタンスを簡単に参照/更新できます。選択・複数選択にも対応。

私は Qt のモデル/ビューの実装の大ファンではありませんが (モデル/ビュー/コントローラーの設計パターンがかなり古いため)、gUI でデータを整理するのに役立ちます。

于 2009-09-02T19:50:12.547 に答える