Lors de l'écriture d'interfaces utilisateur graphiques, j'ai souvent rencontré le problème suivant: Supposons que vous ayez un modèle et un contrôleur. Le contrôleur a un widget W
qui est utilisé pour afficher une propriété X
du modèle. Comme le modèle peut être modifié de l'extérieur du contrôleur (il peut y avoir d'autres contrôleurs utilisant le même modèle, opérations d'annulation, etc.), le contrôleur est à l'écoute des 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.Cycles d'événements de rupture dans les interfaces graphiques
Maintenant, voilà ce qui se passe:
- la valeur
W
est modifiée - un événement est généré, le gestionnaire dans le contrôleur est invoqué
- le contrôleur définit la nouvelle valeur pour
X
dans le modèle - le m odel émet des événements, car il a été modifié
- le contrôleur reçoit un événement de changement du modèle
- le contrôleur obtient la valeur de
X
et fixe dans le widget - goto 1.
Il existe plusieurs solutions possibles pour cela:
- Modifier le contrôleur pour définir un indicateur lorsque le modèle est mis à jour et ne pas réagir aux événements du modèle si ce dernier est défini.
- Débranchez le contrôleur temporairement (ou dire le modèle de ne pas envoyer aucun événement pour un certain temps)
- Gel des mises à jour à partir du widget
Dans le passé, je suis allé plus souvent pour l'option 1., parce qu'il est la chose la plus simple. Il a l'inconvénient d'encombrer vos classes avec des drapeaux, mais les autres méthodes ont aussi leurs inconvénients. Pour l'anecdote, j'ai eu ce problème avec plusieurs toolkits d'interface graphique, y compris GTK +, Qt et SWT, donc je pense que c'est assez agile.
Des meilleures pratiques? Ou l'architecture que j'utilise est-elle simplement incorrecte?
@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, en utilisant le modèle de commande pour annuler/rétablir), car alors la valeur a changé, W
est mis à jour et déclenche un événement. Afin d'éviter 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 ex. une vue arborescente complexe.
J'ai ce problème avec les zones de liste dans MFC tout le temps. –