Question

Lors de la rédaction des interfaces graphiques, je rencontrais souvent le problème suivant: Supposons que vous avez un modèle et un contrôleur. Le contrôleur possède un widget W utilisé pour afficher une propriété X du modèle.

Étant donné que le modèle peut être modifié de l'extérieur du contrôleur (d'autres contrôleurs peuvent utiliser le même modèle, annuler des opérations, etc.), le contrôleur écoute les modifications apportées au modèle. Le contrôleur écoute également les événements sur le widget W et met à jour la propriété X en conséquence.

Les événements suivants se produisent:

  1. la valeur dans W est modifiée
  2. un événement est généré, le gestionnaire dans le contrôleur est appelé
  3. le contrôleur définit la nouvelle valeur de X dans le modèle
  4. .
  5. le modèle émet des événements car il a été modifié
  6. le contrôleur reçoit un événement de modification du modèle
  7. .
  8. le contrôleur obtient la valeur de X et la définit dans le widget
  9. goto 1.

Il existe plusieurs solutions possibles pour cela:

  1. Modifiez le contrôleur pour définir un indicateur lorsque le modèle est mis à jour et ne réagissez à aucun événement du modèle si cet indicateur est défini.
  2. Déconnectez temporairement le contrôleur (ou indiquez au modèle de ne pas envoyer d’événement pendant un certain temps)
  3. Geler les mises à jour du widget

Auparavant, je choisissais généralement l'option 1. Parce que c'est la chose la plus simple. Cela a l’inconvénient d’encombrer vos classes avec des drapeaux, mais les autres méthodes ont aussi leurs inconvénients.

Juste pour mémoire, j'ai eu ce problème avec plusieurs kits d'outils graphiques, y compris GTK +, Qt et SWT, donc je pense que c'est assez toolkit-agnostic.

Des meilleures pratiques? Ou est-ce que l'architecture que j'utilise est tout simplement fausse?

@Shy: C'est une solution dans certains cas, mais vous obtenez toujours une série d'événements superflus si X est modifié de l'extérieur du contrôleur (par exemple, lorsque vous utilisez le modèle de commande pour les fonctions annuler / red ), car la valeur a changé, W est mis à jour et déclenche un événement. Afin d'empêcher une autre mise à jour (inutile) du modèle, l'événement généré par le widget doit être avalé.
Dans d'autres cas, le modèle peut être plus complexe et une simple vérification de ce qui a exactement changé peut ne pas être réalisable, par exemple. une arborescence complexe.

Était-ce utile?

La solution

Généralement, vous devez répondre aux événements saisis dans le widget et ne pas en changer. Cela empêche ce type de boucle de se produire.

  1. L'utilisateur modifie la saisie dans le widget
  2. Le widget émet un événement de changement (défilement effectué / entrer cliqué / laisser la souris, etc.)
  3. Le contrôleur répond, se traduit par un changement de modèle
  4. Le modèle émet un événement
  5. Le contrôleur répond, modifie la valeur du widget
  6. Evénement de changement de valeur émis mais non écouté par le contrôleur

Autres conseils

La façon habituelle pour QT de gérer cela, ainsi que celle suggérée dans leur tutoriel très utile, consiste à modifier la valeur dans le contrôleur uniquement si la nouvelle valeur est différente de la valeur actuelle.
Cela signifie que les signaux ont la sémantique de valueChanged ()

voir ce didacticiel

Drapeaux pour indiquer le travail de mise à jour. Vous pouvez les intégrer à des méthodes telles que BeginUpdate et EndUpdate.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top