web-dev-qa-db-ja.com

シンプルなウィジェットシステムで、各ウィジェットがその親への参照を必要とするのはなぜですか?

私はシンプルなウィジェットシステム(単一ウィンドウ、固定サイズ)に取り組んでいます。各ウィジェットは、その親(つまり、ウィジェットを含むウィジェット)をコンストラクターに渡します。ただし、私が呼び出したルートウィジェットScreenを除きます。

そのアプローチが理にかなっているのか疑問です。以前使用したほとんどのウィジェットシステム(Qt、GTKなど)で実行したためですが、これらは私のものよりもかなり複雑であることに気付きました。

  • ウィンドウのサイズ変更はありません
  • 子供のサイズに基づいてコンテナのサイズを設定する予定はありません
  • メモリ管理には必要ないと思います(C++を使用しています)。代わりに共有ポインタを使用できます(基本的にはJavaでの動作)

ウィジェットがその親への参照を必要とする理由はありますか?

これを変更することは大きなリファクタリングです。したがって、先に進んでコンテナーとレイアウトを実装する前に、その親が必要かどうかをよく理解したいと思います。

編集:とにかく親はすべての子を知っていることに注意してください。子供も親を知る必要があるのか​​と思っています。

8
futlib

あなたが指摘したように、親がすべての作業を行い、子を追跡している限り、子自体が親にアクセスする必要がある場合はめったにありません。ただし、クラシックgetParentは、フレームワークを外部から使用する場合に最も役立ちます。

シナリオ

問題を引き起こす可能性のある単純な操作は次のとおりです。ウィジェットツリー全体のどこかにある2つの具象ウィジェットと、これら2つを交換する必要があるユースケースがある場合、交換はどのように機能しますか?

オプション1:子供に教える

子ウィジェットにswap(withOtherChild)を伝えます。ただし、スワップには、親の子のデータ構造の更新が含まれます。あなたの子供はその親を知らないので、どのようにこれを達成しますか?

オプション2:両親に伝える

子供の親にそれを削除して、もう一方を追加するように伝えます。ああ、同じ問題。子オブジェクトだけがあり、それらにgetParentはありません。

オプション3:グラント作業

最後のオプションとして、hasChild(x)を持つ親とhasChild(y)を持つ親を見つけるためにウィジェットツリー全体をトラバースし、オプション2にフォールバックできます。

解決

大きなウィジェットツリーを構築し、ツリー内のウィジェットの位置を移動する必要がある操作を実行する場合は、親を保持する必要があります。ウィジェットツリーが非常に小さいか、深さが非常に小さいがhasChildアクセサーが高速である場合、オプション3は受け入れられますcould親参照を省略します。

一般的なデータ構造の参照

ここで計画しているのは、ツリーのデータ構造を構築することです。単純化を考えてみましょう。そして議論のために、すべてのウィジェットは子を1つだけ持つことができると仮定します。もちろん、結果はリストであり、あなたの質問は「シングルリンクリストとダブルリンクリストのどちらが必要ですか?」になります。

リストと同じように、明確な答えはありませんが、長所と短所だけがあります。シングルリンク(つまり、親参照がない)の明らかな長所は、a)実装が簡単で、b)メモリが少ないことです。ただし、短所は、a)構造をトラバースする必要があるために一部の操作が遅くなること、b)これらの操作に簡単にアクセスできないことは、データ構造を使用するのが面倒であること、c)より多くのメモリを使用することです。

一方、二重にリンクされたバリアント、つまり親参照を使用すると、これらの長所と短所がかなり逆になります。

ただし、GUIライブラリ/フレームワークに関しては、メモリ制限は通常、親ポインタを禁止する問題ではありません。それを除外し、それがライブラリ/フレームワークであること、したがって実装が難しく、使いやすいことが望ましい場合は、基本的に上記のシングルリンクアプローチの長所を除外します。

私はあなたのプロジェクトの特殊性を認識していません。そのため、上記の私の推論のいくつかはあなたのケースには当てはまらない可能性があるため、親の参照を維持するようにあなたに言わないようにしたいと思います。ただし、一般的には、上記の理由から、ウィジェットデータ構造の親参照は価値があると考えています。

5
Frank

これらのケースのほとんどでは、イベント、シグナル、または状態の変化(または必要に応じて単に子供を破壊するため)の場合に、親と子供の間でかなりの通信が行われています。たとえば、グループ化ボックスは、含まれているラジオボタンを処理して、それらの1つだけが特定の時間に「オン」になるようにします。

この種の機能を計画している場合も、していない場合もあります。個人的に私はそれを持たないウィジェットシステムは多くを提供しないので時間の価値があるかどうか疑問に思います。しかし、それでも私はとにかく既存のソリューションの1つを単に使用します。

2

子供が両親を知っているとき、ウィジェットとそのすべての祖先は 責任の連鎖 を形成すると私は言うでしょう。典型的な例は、ウィジェットが受け取るマウスイベントです。ウィジェットは、イベントを消費する(およびそれに応じて反応する)か、イベントを親に渡すことができます。親は、消費または親に渡すことができます。

Qtの場合、各ウィジェットにはコンストラクタによって親が与えられ、これはウィジェットが親によって所有されていることを示します。特に、親を削除すると、ウィジェットが削除されます。

2
barjak