Une alternative pratique au modèle Signals + Slots pour la programmation GUI?

9

La majorité des boîtes à outils GUI utilisent de nos jours le modèle Signals + Slots. Ce sont Qt et GTK +, si je ne me trompe pas, qui ont été les pionniers.

Vous savez, les widgets ou objets graphiques (parfois même ceux qui ne sont pas affichés) envoient des signaux au gestionnaire de boucle principale. Le gestionnaire de boucle principale appelle ensuite les événements , rappels ou emplacements attribués pour ce widget / objet graphique. Il existe généralement des gestionnaires d' virtualévénements par défaut (et dans la plupart des cas ) déjà fournis par la boîte à outils pour gérer tous les signaux prédéfinis, par conséquent, contrairement aux conceptions précédentes où le développeur devait écrire l'intégralité de la boucle principale et du gestionnaire pour chaque message lui-même (pensez à WINAPI), le développeur n'a qu'à se soucier des signaux dont il a besoin pour implémenter de nouvelles fonctionnalités.

Maintenant que je sache, cette conception est utilisée dans la plupart des boîtes à outils modernes. Il y a Qt, GTK +, FLTK etc. Il y a Java Swing. C # a même une fonction de langue pour cela (événements et délégués), et Windows Forms a été développé sur cette conception. En fait, au cours de la dernière décennie, cette conception pour la programmation GUI est devenue une sorte de norme non écrite. Puisqu'il augmente la productivité et fournit une plus grande abstraction.

Cependant, ma question est:

Existe-t-il une conception alternative, parallèle ou pratique pour la programmation graphique moderne?

c'est-à-dire que la conception Signals + Slots est la seule pratique en ville? Est-il possible de faire de la programmation GUI avec une autre conception? Existe-t-il des boîtes à outils graphiques modernes (de préférence réussies et populaires) construites sur une conception alternative?

ApprenticeHacker
la source
Le paradigme de file d'attente de messages que vous trouvez dans l'API Windows n'est pas comme les événements et les délégués. Les délégués sont appelés de manière synchrone et immédiate, comme std::function, pas un signal asynchrone. En outre, le WinAPI ne fournit DefWindowProcqui traite les messages Windows comme une implémentation par défaut. Je vais donc affirmer que votre question est basée sur une logique défectueuse.
DeadMG
2
QT et GTK + sont loin d'être les premiers frameworks GUI qui utilisaient une approche événementielle. Le concept remonte à Smalltalk-80 ( en.wikipedia.org/wiki/Smalltalk ).
Doc Brown
Question intéressante, je suis curieux de savoir si ce modèle change beaucoup avec les interfaces multi-touch.
Ben DeMott
Je serais généreux et je suppose qu'il connaît SendMessage qui est syncrone, pas seulement PostMessage. Cependant, il a toujours tort en ce que vous n'avez jamais eu à écrire la boucle de gestion des messages entière pour chaque message.
gbjbaanb
JavaFx fournit un mécanisme similaire via ses API de liaisons.
Eng.Fouad

Réponses:

5

C'est un de mes sujets favoris, et pendant environ une décennie (des années 70 à 86), j'ai pensé qu'avoir une interface graphique composée d'objets qui répondent aux événements était juste la bonne façon de le faire.

Ensuite, je suis tombé sur une autre façon de le faire décrite ici et avec un projet sourceforge ici .

En un mot, le problème avec les objets est qu'ils persistent, et si vous écrivez du code pour les créer, vous devez également écrire du code pour les modifier de manière incrémentielle si des changements sont nécessaires, et en quelque sorte obtenir des messages vers et depuis eux. Ce ne serait pas bien si vous pouviez simplement peindre ce que vous vouliez, puis le repeindre si vous voulez quelque chose de différent, sans avoir à vous soucier de la persistance des objets antérieurs? Ne serait-ce pas aussi bien si vous n'aviez jamais à écrire de code pour la gestion des messages, car tout se fait sous le capot?

C'est ce que fait ce paquet. Pour les dialogues simples, il enregistre un ordre de grandeur dans le code. Pour les dialogues complexes à changement dynamique, cela les rend possibles.

PS Je n'ai fait cela que pour les interfaces utilisateur de bureau et les interfaces de terminal distant, pas pour les interfaces utilisateur de navigateur Web. Je suis sûr que c'est possible, mais je n'ai pas eu l'occasion de l'essayer.

Mike Dunlavey
la source
+1, mais comment est-il possible d'obtenir des fonctionnalités supplémentaires, telles que des entrées définies par l'utilisateur?
ApprenticeHacker
@IntermediateHacker: Je ne sais pas ce que vous entendez par entrée définie par l'utilisateur. Voulez-vous dire avoir une application de création de formulaires?
Mike Dunlavey
2

Eh bien, il y a deux façons distinctes de procéder:

  1. Demandez à chaque widget d'exposer un mécanisme d'abonnement granulaire (signal / slot, observateur / observable, événement / délégué) et demandez au code client de s'abonner et d'agir en conséquence.
  2. Construit un widget contre une abstraction des données qu'il présente et demande au code client de mettre en œuvre cette abstraction.

Voici un exemple pour la deuxième approche:

interface Action {
     void execute();
     Bool isEnabled();
     Null<String> description();//used for tooltip
}
interface LabledAction extends Action {
     String getName();
}

Et maintenant, vous pouvez créer un LabelButtoncontre un LabledActionet le code client peut simplement l'implémenter ou utiliser une implémentation générique par défaut, si elle est disponible et appropriée.

D'une certaine manière, la deuxième approche est moins flexible, mais plus rigide. Vous ne vous contentez pas de relier la vue au modèle d'une manière relativement atomique. Vous concevez une interface graphique appropriée en fonction de vos besoins, puis vous implémentez les adaptateurs entre cette interface graphique et votre logique de domaine / application.

back2dos
la source
Le modèle / vue / contrôleur est bon, mais ce n'est qu'une extension du modèle d'observateur, car la partie contrôleur n'est qu'un observateur du widget et dans la partie modèle, le widget est observateur du modèle, c'est donc le même mécanisme dans l'autre sens. .
Jan Hudec
1

Quelques systèmes de type contrôle utilisent une approche de base de données - chaque contrôle gui est lié à un fichier dans la base de données afin que le Gui reflète toujours l'état de la base de données. Les hooks DB sont utilisés pour déclencher des fonctions lorsqu'une valeur change.

Martin Beckett
la source
4
n'est-ce pas encore un signal-slot juste avec une couche DB supplémentaire?
ratchet freak
En fin de compte, ce sont toutes les interruptions ou rappels - ce sont les seules opérations asynchrones de bas niveau
Martin Beckett