Vous êtes sur la page 1sur 5

Version originale : 25 avril 2012

Mise jour : mardi 28 mai 2013

Signaux et slots dans Qt 5


La nouvelle version de Qt vient de sortir en version 5 alpha. Cette version amliore la prise en charge de la nouvelle norme du C++, le C++11, et modifie ainsi le fonctionnement des signaux et slots de Qt. Cet article fait un rappel sur lutilisation des signaux et slots et prsente les nouvelles fonctionnalits offertes par Qt 5.

1 Couplage entre classes et intrt des signaux et slots


Lorsque lon souhaite faire communiquer des objets entre eux, il ncessaire en gnral que les objets se connaissent mutuellement. Par exemple :
class Receiver { public: void slot() { cout << "slot excut" << slot(); } }; class Sender { public: void connect(Receiver* r) { receiver = r; } void signal() { receiver->slot(); } private: Receiver* receiver; }; int main() { // on cre nos objets Receiver receiver; Sender sender; // on connecte le sender et le receiver sender.connect(&receiver); // on met le signal sender.signal(); }

Ce code prsente cependant plusieurs problmes : il faut que la classe Sender connaisse la classe Receiver et cela implique dajouter une dpendance (include) entre ces classes ; Guillaume Belz Signaux et slots dans Qt 5 1/5

Version originale : 25 avril 2012

Mise jour : mardi 28 mai 2013

il est ncessaire de crer une fonction spcifique dans Sender pour chaque type de classe
Receiver et pour chaque slot possible ;

il ne permet pas de grer des connexions vers plusieurs objets Receiver et il faut modifier le code pour grer une liste de Receiver.

Ces contraintes saccumulent dans un framework complexe comme Qt et cela alourdit fortement le code en ajoutant un nombre important de dpendances inutiles. Le code devient trs vite ingrable 1. Le systme des signaux et slots permet de faire de saffranchir de ces contraintes. Il est ainsi possible de faire communiquer des objets entre eux sans quil soit ncessaire que ces objets se connaissent mutuellement. On peut galement choisir lors de la connexion le slot que lon souhaite appeler lorsque le signal est mis. On passe ainsi dun couplage fort (ncessit davoir une dpendance) un couplage faible (plus de dpendance ncessaire) et lon parle de dcouplage des classes.

2 Le systme des signaux et slots dans Qt


Le systme de signaux et slots de Qt est relativement simple. Lorsquun vnement se produit, un signal est mis. Tous les slots qui sont connects ce signal sont alors excuts. La fonction
QObject::connect permet de crer une telle connexion. La forme la plus classique de cette

fonction prend en paramtres un pointeur vers lobjet metteur, le nom du signal (ainsi que la liste des types des arguments du signal), un pointeur vers lobjet rcepteur et pour terminer le nom du slot (ainsi que la liste des types des arguments du slot). Il est possible de connecter plusieurs signaux un mme slot, un signal plusieurs slots ou un signal avec un signal. Le compatibilit entre les classes et les signaux et slots est vrifis lors de la compilation.
QAction a; QWidget w; QObject::connect(&a, SIGNAL(triggered()), // connecte le signal triggered() de QAction &w, SLOT(show())); // au slot show() de QWidget

1 Il est possible dutiliser dautres approches que celle prsente ici. En particulier, on peut utiliser les pointeurs de fonctions ou quivalents (callback). Le lecteur intress par la question pourra par exemple tudier lapproche utilise dans Boost.Signals. Guillaume Belz Signaux et slots dans Qt 5 2/5

Version originale : 25 avril 2012

Mise jour : mardi 28 mai 2013

Les classes de Qt fournissent de nombreux signaux et slots par dfaut. Ces signaux et slots seront disponibles dans les classes cres par les utilisateurs et drivant des classes de Qt. Il est galement possible de crer ses propres signaux et slots et de les connecter aux signaux et slots par dfaut de Qt. Remarque : il est ncessaire de mettre les dclaration des classes drives de QObject dans des fichiers den-tte et non dans un fichier dimplmentation, sinon, le systme de pr-compilation de Qt ne pourra pas fonctionner.
#include <QObject>

class Counter : public QObject { // on hrite de QObject pour bnficier des mta-informations de Qt Q_OBJECT // cette macro permet de gnrer les // signaux et slots lors de la compilation public slots: void setValue(int value) { if (value != m_value) { // lorsque la valeur est change m_value = value; emit valueChanged(value); // on met un signal valueChanged } } signals: void valueChanged(int newValue); // signal mis lorsque la valeur est change private: int m_value; };

Et dans le main.cpp :
int main() { Counter a, b; // on connecte valueChanged de a setValue de b Qobject::connect(&a, &Counter::valueChanged, &b, &Counter::setValue);

Guillaume Belz

Signaux et slots dans Qt 5

3/5

Version originale : 25 avril 2012

Mise jour : mardi 28 mai 2013

a.setValue(12); // a met un signal valueChanged qui active le slot setValue de b // a.value() == 12, b.value() == 12 b.setValue(48); // b met un signal valueChanged mais ce signal n'est pas connect // un slot : a.value() == 12, b.value() == 48 }

3 Crer une connexion dans Qt 5


Dans Qt 4, il est possible de connecter uniquement les fonctions dclares comme signaux et slots dans la classes, comme indiqu dans le code dexemple prcdant. Dans Qt 5, il est maintenant possible de connecter directement des pointeurs de fonctions ou dutiliser des fonctions lambdas. La connexion de pointeurs de fonctions est similaire une connexion classique, en donnant un pointeur sur les objets et sur les fonctions. Les classes mettrices et rceptrices doivent driver de
QObject mais il nest pas ncessaire de dclarer les fonctions slots avec le mot cl slots.
class Sender : public QObject { Q_OBJECT signals: void send(int i = 0); }; class Receiver : public QObject { Q_OBJECT public: void receive(int i = 0) { qDebug() << "Receiver.receive :" << i; } }; // Utilisation avec les pointeurs de fonctions QObject::connect(&sender, &Sender::send, &receiver, &Receiver::receive); emit sender.send(2); sender.disconnect();

Lavantage de cette criture est que la compatibilit des paramtres est effectue lors de la compilation et non lors de lexcution. Guillaume Belz Signaux et slots dans Qt 5 4/5

Version originale : 25 avril 2012 Pour les fonctions lambdas :


// Utilisation avec les fonctions lambdas QObject::connect(&sender, &Sender::send,

Mise jour : mardi 28 mai 2013

[&receiver](int i = 0){ receiver.receive(i); }); emit sender.send(3);

Dans ce code, on capture le pointeur vers lobjet rcepteur et on rcupre le paramtre pass par la fonction send puis on appelle dans le corps de la lambda le fonction receive. Le rsultat obtenu est identique au code prcdant, mais il est possible de faire beaucoup dautres choses dans la lambda (par exemple dconnecter tous le signaux ou parcourir tous les enfants de lobjet rcepteur). Si le compilateur utilis ne support pas les variadics templates, les signaux et slots doivent avoir moins de 6 paramtres.

4 Remarques
Vous pouvez tlcharger un projet dexemple montrant ces nouvelles fonctionnalits en action : la page de tlchargement. Les images et codes dexemple sont issus de la documentation de Qt5 disponible cette page : Qt 5.0: Signals & Slots.

Guillaume Belz

Signaux et slots dans Qt 5

5/5

Vous aimerez peut-être aussi