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


8

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

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

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

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

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

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

回答:


5

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

シナリオ

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

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

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

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

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

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

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

解決

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

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

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

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

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

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

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


2

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

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


1
私がそうであるように、親が子供を知っているとき、それらすべてが可能であるように見えます。子供が親も知る必要があるのか​​と思っています。
futlib

私は既存のものを喜んで使用しますが、ここではかなりユニークな環境にあり、独自のシンプルなシステムが最善のアプローチであると考えました。
futlib

もちろん理由は常にあり、たとえばQtはかなり重いです。子が親を知る必要があるのは、作成時に登録したり、後で状態の変更を送信したりできるようにするためです。
Thorstenmüller2013年

つまり、ラジオボタンがクリックされたときに、親に通知して、以前にチェックしたもののチェックを外すことができるようにする必要があるのでしょうか。はい、私はそれが子供と親の関係なしでは難しいと思います...他の例を考えることができますか?
futlib

2
「サイズと位置に基づく」は、非常に厄介なコードを残す可能性があります。イベントを少しずつ流していきたいと思います。親がクリックイベントを取得するように、自分の位置とサイズ情報に基づいて決定する責任があるかどうか、子に「質問」します。他の例?ウィジェットの複雑さによって異なります。彼らはそんなに複雑ではないだろうと言います。しかし、反対に、最初から親ポインターを追加しても、それほど害はなく、必要なときにそれらを使用できます。スクロールバーは、私が推測するもう1つの良い例です。彼らは親にスクロールすることを報告し、親はビューに更新するように伝えます。
Thorstenmüller2013年

2

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.