Frage

Beim Schreiben von GUIs, ich habe über das folgende Problem, das häufig kommen: Angenommen, Sie haben ein Modell und eine Steuerung. Der Controller verfügt über einen Widget W die verwendet wird, eine Eigenschaft X des Modells zu zeigen.

Da das Modell von außerhalb der Steuerung geändert werden könnte (es könnten auch andere Controller sein, das gleiche Modell, Undo-Operationen, etc.), der Controller hört auf das Modell ändert. Der Controller auch hört Ereignisse auf dem Widget W und aktualisiert die Eigenschaft X entsprechend.

Nun geschieht Folgendes:

  1. der Wert in W geändert
  2. ein Ereignis erzeugt wird, der Handler in der Controller wird aufgerufen
  3. Controller setzt den neuen Wert für X in dem Modell
  4. Modell emittiert Ereignisse, weil es geändert wurde
  5. Controller erhält ein Änderungsereignis aus dem Modell
  6. Controller wird der Wert von X und setzt es im Widget
  7. gehe zu 1.

Es gibt mehrere mögliche Lösungen dafür:

  1. Controller Ändern ein Flag zu setzen, wenn das Modell aktualisiert wird, und nicht auf irgendwelche Ereignisse aus dem Modell reagieren, wenn dieser Flag gesetzt ist.
  2. Ziehen Sie den Controller vorübergehend (oder das Modell sagen, keine Ereignisse für einige Zeit zu senden)
  3. Frieren
  4. kein Updates aus dem Widget

In der Vergangenheit ging ich in der Regel für die Option 1, weil es die einfachste Sache ist. Es hat den Nachteil, Ihre Klassen mit Fahnen unübersichtlich, aber die anderen Methoden haben ihre Nachteile, auch.

Nur für das Protokoll, habe ich dieses Problem mit mehreren GUI-Toolkits hatte, einschließlich GTK +, Qt und SWT, so dass ich denke, es ist ziemlich Toolkit-Agnostiker.

Jede Best Practices? Oder ist die Architektur ich einfach falsch benutzen?

@Shy: Das ist eine Lösung für einige Fälle, aber immer noch eine Runde überflüssiger Ereignisse, wenn X von außerhalb der Steuerung geändert wird (zum Beispiel, wenn für Undo / Redo den Befehl Muster verwendet wird), denn dann hat der Wert veränderte, W wird aktualisiert und feuert ein Ereignis. Um einen anderen (nutzlosen) Update für das Modell zu verhindern, wird das Ereignis durch das Widget erzeugt hat geschluckt werden.
In anderen Fällen könnte sein, das Modell komplexen und eine einfache Kontrolle darüber, was genau geändert hat vielleicht nicht möglich sein, z.B. eine komplexe Baumansicht.

War es hilfreich?

Lösung

In der Regel sollten Sie auf Eingabeereignisse im Widget reagieren und nicht Ereignisse zu ändern. Dies verhindert, dass diese Art von Schleife aus auftritt.

  1. Benutzer ändert Eingang im Widget
  2. Widget emittiert Änderungsereignis (SCROLL / enter geklickt / Maus verlassen, etc.)
  3. Controller reagiert, übersetzt im Modell
  4. ändern
  5. Modell emittiert Ereignis
  6. Controller reagiert, ändert Wert in Widget
  7. Wertänderungsereignis ausgestrahlt wird, aber nicht hörte von Controller

Andere Tipps

Die Standard-QT Art und Weise des Umgangs mit dieser und auch die eine in ihren sehr nützlich Tutorial vorgeschlagen, die Änderung auf den Wert in der Steuerung zu machen, nur dann, wenn der neue Wert vom aktuellen Wert abweicht.
Dies ist Art und Weise Signale haben die Semantik von valueChanged()

dieses Tutorial

Flags, um anzuzeigen, Arbeit zu aktualisieren. Sie können sie in Methoden wie Beginupdate und EndUpdate wickeln.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top