Qt slot et signal

À chaque fois que j’explique que je suis rebuté par Qt à cause de son intrusivité dans le programme, que ce n’est pas vraiment du c++, on me parle des slots et des signaux. D’une manière générale ça semble être LA fonctionnalité qui plait…

Pour ma culture personnel j’essaie de me mettre un peu à Qt. J’ai le site du zéro sur le sujet : siteduzero.com/tutoriel-3-11 … slots.html

C’est moi, eux qui expliquent mal ou c’est de la daube ?

D’une part boost fait mieux (comme toujours ?) : boost.org/doc/libs/1_50_0/do … #id3160297

D’autre part pourquoi faire un truc aussi compliqué quand le gang des 4 nous a sorti le design pattern « Listener » qui est à la fois trivial à implémenter, à utiliser et à comprendre ? D’autant plus que c’est un concept qui fonctionne dans tout les langages objets.

C’est une vraie question il y a quelque chose de mieux dans les slots/signaux par rapport à l’usage d’objet de rappel ?

J’ai aussi un problème relationnel avec Qt et son utilisation du C++
On a l’impression que les développeurs ont recodé la std…

L’utilisation de Qt rend la compilation très compliquée (qmake).

Il me semble que leur argument est / était un truc du genre:

  • Les compilateurs ne respectent pas tous le standard
  • Ils n’implantent pas tous la std / stl

Qt5 se rapprochera plus du C++
woboq.com/blog/new-signals-slots … n-qt5.html

Cela dit, les signaux et les slots sont assez élégants et pratiques (par rapport à Java par exemple).

Tu as un lien / explication pour ce design pattern ?
Car si tu parles de l’observer, Qt signal / slot est une implantation
en.wikipedia.org/wiki/Observer_pattern#C.2B.2B

«objet de rappel» ?

[quote=“Eho”]Qt5 se rapprochera plus du C++
woboq.com/blog/new-signals-slots … n-qt5.html[/quote]
T’inquiète pas ils garderont qmake…

Moi j’aime pas pour plusieurs raison :
[ul]
[li]Ça se base énormément sur l’héritage QObject et sur du code généré par moc, on est très loin d’être KISS[/li]
[li]la méthode connect est problématique car elle utilise des chaines de caractères ce qui rend plus compliquée l’analyse statique, cela va à l’encontre des modèles objets[/li]
[li]histoire d’aller un peu plus loin à l’encontre de l’objet et de rendre le truc un peu moin kiss on crée deux concepts les signaux et les slots, au lieu de simplement réutiliser l’existant qui marche bien[/li][/ul]

Tu as un lien / explication pour ce design pattern ?
Car si tu parles de l’observer, Qt signal / slot est une implantation
en.wikipedia.org/wiki/Observer_pattern#C.2B.2B[/quote]
Tu as raison je devais être fatigué hier soir. Ça ne change pas que c’est une implémentation pourrie, qui utilise :
[ul]
[li]2 concepts : les slots et les signaux[/li]
[li]2 macros : SIGNAL() et SLOT()[/li]
[li]1 méthode plus ou moins magique : QObject::connect()[/li]
[li]un mot clef et une instruction spécifique toute nouvelle : emit[/li][/ul]
Pour faire ce que tout le monde fait très bien avec des interfaces (ou classes abstraites) et des méthodes tout à fait classique.

«objet de rappel» ?[/quote]
Au lieu d’avoir une fonction callback (ou plutôt un pointeur ou une référence vers celle-ci) et de l’appeler. On utilise un objet. Un Widget comme le QPushButon a une méthode addClickListener(const ClickListener &), ça peut se factoriser dans une classe abstraite à dériver pour chaque widget cliquable. Au lieu de créer un slot ont implémente la classe abstraite ClickListener qui demande de créer les méthodes clicked(), released(), etc.

C’est simple à mettre en place (aucune magie derrière, à la rigueur un peu de technique pour être résistant au problèmes de multithreading, mais rien de plus).

Entièrement d’accord avec toi, j’ai pas mis mon avis personnel pour pas lancer de troll :wink:
(Pour moi) Qt c’est du C-- (et vu la compilation, je ne considère même pas ça comme du C++)

Je disais juste que les signaux et les slots sont un concept qui me plaît:
Tu lies un objet (signal) avec une fonction (slot); au final tu as juste à donner une fonction que l’objet déclenche "tout seul"
Après je pense aussi que l’implantation de Qt est pourrie :astonished:

Pour l’objet de rappel, à une première lecture, ça ressemble à ce que fait Java. (Il doit avoir moyen d’éviter ça, mais) en pratique, tu as des cast dans tous les sens pour savoir quel élément a été cliqué si tu lies plusieurs éléments à un même ClickListener (c’est plus facile/rapide (…) d’avoir un seul ClickListener qui connaît ta fenêtre ou tes données à modifier).

Je préfere boost aussi et utilise Qt uniquement pour la gui et tout ce que boost ne sait pas faire.

Mais pour que tu comprennes mieux son engouement je pense qu’il faut le voir comme ça

Qt = ubuntu
boost = debian

Donc pour ceux qui savent utiliser le c++ cela apporte qu’ un petit plus de temps en temps mais ce n’est que mon avis.

Suffit de coder la même appli en boost et l autre en Qt pour s 'apercevoir de la suprematie de boost.

Non c’est ce que fait Java.

Il n’y a pas de cast, ça utilise uniquement le polymorphisme : une base essentiel du modèle objet par classe. Tout est vérifié statiquement à la compilation.

Voici un petit exemple (il a des problèmes) :
http://paste.isalo.org/117

C’est peut être un peu verbeux, mais c’est simple.

Je connais boost et la qualité de celui-ci. Note que boost n’est pas parfait. Pour les matrices j’ai préféré utiliser eigen :
eigen.tuxfamily.org/index.php?title=Main_Page

[quote=“MisterFreez”]Pour les matrices j’ai préféré utiliser eigen :
eigen.tuxfamily.org/index.php?title=Main_Page[/quote]
HS: Avec Boost pour les matrices, faut ajouter le DEFINE NDEBUG sinon les perfs :confused:

Bien sûr il vaut mieux faire son bench soit même mais celui-ci est intéressant :
eigen.tuxfamily.org/index.php?title=Benchmark

Moi personnellement c’est l’API que j’ai trouvé plus agréable, la performance n’était pas le plus important.

Les signaux/slots Qt ont tout de même une grosse spécificité : la prise en charge du multithreading.

Qt permet d’associer chaque objet avec un thread spécifique, dans lequel s’exécuteront tous les slots de cet objet appelés par un signal (un appel direct au slot se comportera comme s’il s’agissait d’une méthode normale, donc s’exécutera dans le thread de l’appelant).
Les signaux et les arguments pour le slot sont automatiquement dispatchés à chaque thread en fonction des besoins tout en garantissant la synchronisation entre threads.

Pour bien comprendre l’intérêt, il faut se rappeler que Qt n’est pas juste un toolkit graphique, mais a vocation à être une plate-forme complète pour faciliter la portabilité des applications.
Donc il y a toute une flopée de classes non-graphiques (au hasard : réseau, filesystem, …) qui sont concernées par ce mécanisme.

Exemple classique : toute la couche réseau va être associée à un (ou plusieurs) thread(s) donné(s), et ne communiquera avec le reste du programme que par signaux/slots.

Cette spécificité des signaux/slots permet d’augmenter le parallélisme presque sans aucun coût pour le programmeur, très souplement (granularité au niveau des objets individuels).

[quote=“syam”]Qt permet d’associer chaque objet avec un thread spécifique, dans lequel s’exécuteront tous les slots de cet objet appelés par un signal (un appel direct au slot se comportera comme s’il s’agissait d’une méthode normale, donc s’exécutera dans le thread de l’appelant).
Les signaux et les arguments pour le slot sont automatiquement dispatchés à chaque thread en fonction des besoins tout en garantissant la synchronisation entre threads.[/quote]

[quote=“syam”]Pour bien comprendre l’intérêt, il faut se rappeler que Qt n’est pas juste un toolkit graphique, mais a vocation à être une plate-forme complète pour faciliter la portabilité des applications.
Donc il y a toute une flopée de classes non-graphiques (au hasard : réseau, filesystem, …) qui sont concernées par ce mécanisme.

Exemple classique : toute la couche réseau va être associée à un (ou plusieurs) thread(s) donné(s), et ne communiquera avec le reste du programme que par signaux/slots.[/quote]
Je le sais parfaitement. C’est marrant de devoir ressortir ça pour expliquer alors qu’une ihm c’est de toute manière multithreadé de base par nécessité. Alors que justement les derniers serveurs utilisent plutôt de l’asynchronisme. :slightly_smiling:

Tu parle de coût en terme de facilité de développement j’espère. Parce que sinon tu t’es laissé bourré le mou par une plaquette publicitaire. Le parallélisme entraine en coût quoi qu’il arrive. Il y a de la synchronisation à mettre en place, déterminer si tu es optimiste ou pas, comment sont accéder tes ressources partagées, etc.

Mais ça m’intéresse beaucoup ce que tu dis. C’est le genre de truc dont j’avais l’impression de passer à coté. Tu veux dire que Qt va créer des threads, dispatcher les objets dans les threads et que lors du emit c’est le thread de l’objet du slot qui va s’exécuter ?

Faut que je dorme dessus pour y repenser (j’ai écris ce message ce matin et depuis j’attends d’avoir un peu de temps de cerveau libre pour y réfléchir) et comparer avec le pattern observer.

Merci beaucoup

Oui, « aucun coût pour le programmeur » signifiait bien « aucun coût de développement ».

Qt permet justement de simplifier un peu tout ça, d’autant que l’archi de la lib s’y prête bien : les signaux/slots permettent de découpler les classes donc il y a peu de ressources partagées et assez peu de besoins de synchronisation manuelle.

Grosso modo c’est ça. Tu crées des threads en fonction de tes besoins, tout nouvel objet est automatiquement attaché au thread courant mais il est possible de le réattacher à un autre thread ensuite. Ça permet pas mal de souplesse sans pour autant devenir envahissant.
En réalité l’implémentation sous le capot c’est une boucle de messages dans chaque thread, chaque signal générant un message adéquat qui sera posté à la boucle de messages du thread adéquat. On peut même choisir finement la manière de traiter une connexion signal/slot donnée (appel direct dans un même thread, message asynchrone, message synchrone, …).