6

私のプロジェクトの 1 つで、QObject の親/子機能を利用してツリーを構築する QObject 派生オブジェクトのツリーがあります。

シグナルとスロットを利用し、Qt の保護されたポインターを使用し、親オブジェクトが削除されたときに子を削除することを期待しているため、これは非常に便利です。

ここまでは順調ですね。残念ながら、私のプロジェクトでは、子の順序を管理/変更する必要があります。QObject は、その子の順序を変更する手段を提供しません (例外: QWidget の raise() 関数 - ただし、この場合は役に立ちません)。だから今、私は子供たちの順序を制御する戦略を探しています。いくつかのアイデアがありましたが、それらの長所と短所についてはわかりません。



オプション A:カスタム ソート インデックス メンバー変数

int m_orderIndexメンバー変数をソートキーとして使用し、sortedChildren()このキーでソートされた QObjects のリストを返すメソッドを提供します。

  • 既存のオブジェクト構造に簡単に実装できます。
  • QObject::children()メソッドがオーバーライドされると問題があります - アイテムの順序が変更されたときにループ中に問題が発生し、デフォルトの実装よりもコストがかかります。
  • すべてのソートキーが等しいか、0/デフォルトの場合、QObject オブジェクトの順序にフォールバックする必要があります。

オプション B:子の冗長リスト

で子の冗長リストを維持し、QList作成および破棄されたときに子を追加します。

  • 追加/削除されたオブジェクトの高価な追跡が必要です。これは基本的に、2 番目の子/親の追跡と多くのシグナル/スロットにつながります。QObject はすでに内部的にこれをすべて行っているため、もう一度行うのは得策ではないかもしれません。また、子供の順序を変更するなどの単純なことに、多くの肥大化が追加されているように感じます.
  • 子の QList は必要に応じて変更できるため、優れた柔軟性。
  • 子が QList に複数回存在することを許可するか、またはまったく存在しないことを許可します (たとえそれがまだ QObject の子である場合でも)。

オプション C: ...?

特に自分のプロジェクトでこれをすでに解決した人からのアイデアやフィードバックは大歓迎です。明けましておめでとう!

4

5 に答える 5

7

私は過去数日間、これらすべてのオプションを検討するのに多くの時間を費やし、他のプログラマーと慎重に議論しました。オプション Aを選択することにしました。

管理している各オブジェクトは、親オブジェクトの子です。Qt はこれらのオブジェクトを並べ替える手段を提供しないため、int m_orderIndex各オブジェクトにプロパティを追加することにしました。デフォルトは 0 です。

各オブジェクトには、子のsortedChildren()を返すアクセサ関数がありますQObjectList。その関数で行うことは次のとおりです。

  1. 通常のQObject::chilren()関数を使用して、使用可能なすべての子オブジェクトのリストを取得します。
  2. dynamic_castm_orderIndexプロパティを提供する「基本クラス」へのすべてのオブジェクト。
  3. オブジェクトがキャスト可能な場合は、一時オブジェクト リストに追加します。
  4. qSortカスタム関数で使用しLessThanて、qSort が 2 つのオブジェクトの順序を変更する必要があるかどうかを調べます。
  5. 一時オブジェクト リストを返します。

これを行った理由は次のとおりです。

  • 既存のコード (特に Qt 独自のコード) はchildren()、副作用を心配することなく引き続き使用できます。
  • children()パフォーマンスを損なうことなく、順序が問題にならない場所で通常の関数を使用できます。
  • 子の順序付きリストが必要な場所では、単純に置き換えchildren()sortedChildren()、目的の効果を得ます。

このアプローチの良い点の 1 つは、すべてのソート インデックスがゼロに設定されている場合、子の順序が変わらないことです。

私自身の質問に答えて申し訳ありませんが、同じ問題を抱えている人々を啓発することを願っています。;)

于 2010-01-09T00:57:09.373 に答える
0

別のオプション C はありませんが、オプション A と B を比較すると、どちらの場合も最大 4 バイト (32 ビット ポインター、32 ビット整数) を話しているので、オプション B を使用します。そのリストがソートされました。

子の追跡がさらに複雑になるのを避けるために、ごまかしてリストを並べ替えて整理しておくことができますが、子以外をすべて除外する sortedChildren メソッドと組み合わせることができます。複雑さに関して言えば、これは O(nlogm) (n = 子、m = リスト エントリ、m >= n と仮定すると、つまり、子は常に追加されます) のあたりで終わります。このオプションを C としましょう。

提案されたオプションAのクイックソートは、O(n2)(wc)を提供しますが、ポインターの取得、トレース、整数の取得なども必要とします。組み合わせた方法では、ポインターのリストのみが必要です(Oである必要はありません(n))。

于 2010-01-02T21:42:56.440 に答える
0

厄介なハック: QObject::children()は const への参照を返します。const-ness をキャストすることで、内部リストを直接操作できます。

ただし、これはかなり悪質であり、QObject が内部的に保持しているイテレータを無効にするリスクがあります。

于 2010-01-02T14:50:22.640 に答える