Warum sollte jedes Widget in einem einfachen Widget-System einen Verweis auf sein übergeordnetes Widget benötigen?

8

Ich arbeite an einem einfachen Widget-System (einzelnes Fenster, feste Größe). Jedes Widget erhält sein übergeordnetes Widget (dh das Widget, das es enthält) an seinen Konstruktor übergeben - mit Ausnahme des Root-Widgets, das ich Screen genannt habe .

Ich habe einige Zweifel, ob dieser Ansatz sinnvoll ist. Ich habe es getan, weil die meisten Widget-Systeme, die ich zuvor verwendet habe (Qt, GTK, ...), aber ich habe festgestellt, dass diese etwas komplexer sind als meine:

  • Ich habe keine Fenstergröße
  • Ich habe nicht vor, Container anhand der Größe ihrer Kinder zu dimensionieren
  • Ich glaube nicht, dass ich es für die Speicherverwaltung brauche (ich verwende C ++), ich kann stattdessen gemeinsam genutzte Zeiger verwenden (im Grunde würde es in Java funktionieren).

Gibt es einen Grund, warum ein Widget einen Verweis auf sein übergeordnetes Element benötigt?

Es ist eine große Umgestaltung, dies zu ändern. Bevor ich also Container und Layouts implementiere, möchte ich eine gute Vorstellung davon haben, ob ich diesen Elternteil brauche oder nicht.

Bearbeiten: Bitte beachten Sie, dass die Eltern sowieso alle ihre Kinder kennen. Ich frage mich nur, ob die Kinder auch die Eltern kennen müssen.

Futlib
quelle

Antworten:

5

Wie Sie bereits betont haben, muss das Kind selbst selten, wenn überhaupt, auf das Elternteil zugreifen müssen, solange das Elternteil die gesamte Arbeit erledigt und den Überblick über seine Kinder behält. Der Klassiker getParentist jedoch am nützlichsten, wenn Sie das Framework von außen verwenden.

Szenario

Eine einfache Operation, die Probleme verursachen kann, ist die folgende: Wie funktioniert das Austauschen, wenn zwei konkrete Widgets irgendwo in Ihrem gesamten Widget-Baum vorhanden sind und ein Anwendungsfall vorliegt, bei dem Sie diese beiden austauschen müssen?

Option 1: Sagen Sie es den Kindern

Sagen Sie es Ihrem Kinder-Widget swap(withOtherChild). Beim Austauschen wird jedoch die Datenstruktur der untergeordneten Kinder auf irgendeine Weise aktualisiert. Wie erreichen Sie dies, da Ihr Kind seine Eltern nicht kennt?

Option 2: Sagen Sie es den Eltern

Bitten Sie die Eltern eines Kindes, es zu entfernen und das andere hinzuzufügen. Oh warte, das gleiche Problem. Sie haben nur die untergeordneten Objekte und es gibt keine getParentauf diesen.

Option 3: Grunzarbeit

Als letzte Option können Sie Ihren gesamten Widget-Baum durchlaufen, um ein übergeordnetes Element mit hasChild(x)und eines mit zu finden, hasChild(y)und dann auf Option 2 zurückgreifen.

Lösung

Sie sollten das übergeordnete Element behalten, wenn Sie jemals große Widget-Bäume erstellen und Vorgänge ausführen möchten, bei denen die Position eines Widgets im Baum verschoben werden muss. Wenn Ihre Widget-Bäume sehr klein sind oder nur eine sehr geringe Tiefe, aber schnelle hasChildZugriffsmethoden haben, ist Option 3 möglicherweise für Sie akzeptabel und Sie können die übergeordnete Referenz weglassen.

Referenzen in Datenstrukturen im Allgemeinen

Sie planen hier, eine Datenstruktur für einen Baum aufzubauen. Betrachten wir eine Vereinfachung und nehmen wir aus Gründen der Argumentation an, dass jedes Widget nur ein Kind haben kann. Das Ergebnis ist natürlich eine Liste, und Ihre Frage lautet nun "Soll ich eine einfach oder doppelt verknüpfte Liste haben?".

Und genau wie bei Listen gibt es keine eindeutige Antwort, sondern nur Vor- und Nachteile. Offensichtliche Vorteile für Single-Linked (dh keine übergeordnete Referenz) sind a) einfacher zu implementieren und b) weniger Speicher. Zu den Nachteilen gehören jedoch a) einige Operationen werden langsam, da sie die Struktur durchlaufen müssen, und b) ein nicht einfacher Zugriff auf diese Operationen kann bedeuten, dass die Verwendung der Datenstruktur umständlich ist, und c) sie verwendet mehr Speicher.

Andererseits kehrt die doppelt verknüpfte Variante, dh mit übergeordneter Referenz, diese Vor- und Nachteile ziemlich um.

In Bezug auf eine GUI-Bibliothek / ein GUI-Framework sind die Speicherbeschränkungen normalerweise kein Problem, das übergeordnete Zeiger verbietet. Wenn Sie dies ausschließen und feststellen, dass es sich um eine Bibliothek / ein Framework handelt und es daher vorzuziehen ist, dass es schwer zu implementieren, aber einfach zu verwenden ist, schließen Sie die oben genannten Vorteile eines Single-Linked-Ansatzes im Wesentlichen aus.

Ich bin mir der Besonderheiten Ihres Projekts nicht bewusst, daher möchte ich Sie nicht auffordern, die übergeordnete Referenz beizubehalten, da einige meiner obigen Überlegungen in Ihrem Fall möglicherweise nicht zutreffen. Im Allgemeinen halte ich übergeordnete Referenzen in einer Widget-Datenstruktur aus den oben genannten Gründen jedoch für sinnvoll.

Frank
quelle
2

In den meisten dieser Fälle findet eine gewisse Kommunikation zwischen Eltern und Kindern statt, wenn Ereignisse, Signale oder Zustandsänderungen auftreten (oder wenn nötig, um Kinder einfach zu zerstören). Beispielsweise kann ein Gruppierungsfeld die darin enthaltenen Optionsfelder verarbeiten, um sicherzustellen, dass zu einem bestimmten Zeitpunkt nur eines davon aktiviert ist.

Möglicherweise planen Sie eine solche Funktionalität oder nicht. Persönlich würde ich bezweifeln, dass ein Widget-System ohne es die Zeit wert ist, da es nicht viel bieten würde. Aber dann würde ich einfach eine der vorhandenen Lösungen verwenden.

thorsten müller
quelle
1
All das scheint möglich zu sein, wenn die Eltern ihre Kinder kennen, was bei mir der Fall ist. Ich frage mich nur, ob das Kind auch die Eltern kennen muss.
Futlib
Ich würde gerne etwas Vorhandenes verwenden, aber wir befinden uns hier in einer ziemlich einzigartigen Umgebung und haben festgestellt, dass unser eigenes einfaches System der beste Ansatz ist.
Futlib
Es gibt natürlich immer Gründe und Qt zum Beispiel ist ziemlich schwer. Der Grund, warum das Kind seine Eltern kennen muss, besteht hauptsächlich darin, dass es sich bei der Erstellung registrieren oder später Statusänderungen senden kann.
Thorsten Müller
Sie meinen, wenn ein Optionsfeld angeklickt wird, muss es das übergeordnete Element informieren, damit das zuvor angekreuzte deaktiviert werden kann? Ja, ich denke, das wäre ohne die Verbindung zwischen Kind und Eltern schwierig. Können Sie sich andere Beispiele vorstellen?
Futlib
2
"Basierend auf Größe und Position" könnte Ihnen wirklich bösen Code hinterlassen. Ich würde es vorziehen, Ereignisse herunterzulaufen. Wenn ein Elternteil ein Klickereignis erhält, "fragt" es seine Kinder, ob sie dafür verantwortlich sind, was sie anhand ihrer eigenen Positions- und Größeninformationen entscheiden. Andere Beispiele? Hängt davon ab, wie komplex Ihre Widgets sind. Sie sagen, dass sie nicht so kompliziert sein werden. Aber auf der anderen Seite: Wenn Sie den übergeordneten Zeiger von Anfang an hinzufügen, tut das nicht viel weh und Sie haben sie, wenn Sie sie brauchen. Bildlaufleisten sind ein weiteres gutes Beispiel, denke ich. Sie melden das Scrollen an das übergeordnete Element. Das übergeordnete Element teilt der Ansicht mit, dass sie aktualisiert werden soll.
Thorsten Müller
2

Ich würde sagen, wenn die Kinder ihre Eltern kennen, bilden ein Widget und alle seine Vorfahren eine Verantwortungskette . Ein typisches Beispiel ist ein Mausereignis, das von einem Widget empfangen wird: Das Widget kann entweder das Ereignis konsumieren (und entsprechend reagieren) oder das Ereignis an sein übergeordnetes Ereignis übergeben, das es entweder konsumieren oder an sein übergeordnetes Element übergeben kann, usw.

Im Fall von Qt erhält jedes Widget vom Konstruktor sein übergeordnetes Element. Dies zeigt an, dass das Widget dem übergeordneten Element gehört. Insbesondere das Löschen des übergeordneten Elements löst das Löschen des Widgets aus.

Barjak
quelle