Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zéro > Les tutoriels > Officiels > Programmation > Apprenez à programmer en C++ ! > [Pratique] Créez vos propres fenêtres avec Qt > Les signaux et les slots > Lecture du tutoriel

Les signaux et les slots

Avatar
Auteur : M@teo21
Note : 18 / 20 (9 votes)
Visualisations : 55 174

Plus d'informations Plus d'informations
Nous commençons à maîtriser petit à petit la création d'une fenêtre. Dans le chapitre précédent, nous avons posé de solides bases pour développer par la suite notre application. Nous avons réalisé une classe personnalisée, héritant de QWidget.

Nous allons maintenant découvrir le mécanisme des signaux et des slots, un principe propre à Qt qui est clairement un de ses points forts. Il s'agit d'une technique séduisante pour gérer les évènements au sein d'une fenêtre.
Par exemple, si on clique sur un bouton, on voudrait qu'une fonction soit appelée pour réagir au clic. C'est précisément ce que nous apprendrons à faire dans ce chapitre, qui va enfin rendre votre application dynamique :)
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Le principe des signaux et slots

Le principe est plutôt simple à comprendre : une application de type GUI réagit à partir d'évènements. C'est ce qui rend votre fenêtre dynamique.
Ceux d'entre vous qui ont déjà essayé la bibliothèque SDL se souviennent peut-être de la gestion des évènements : interception des touches du clavier, des déplacements de la souris, du joystick, etc.

Ce que Qt propose, c'est la même chose mais à plus haut niveau : c'est donc beaucoup plus facile à gérer.

On parle de signaux et de slots, mais qu'est-ce que c'est concrètement ? C'est un concept inventé par Qt. Voici une petite définition en guise d'introduction :



Les signaux et les slots sont considérés par Qt comme des éléments d'une classe à part entière, en plus des attributs et des méthodes.

Voici un schéma qui montre ce qu'un objet pouvait contenir avant Qt, ainsi que ce qu'il peut contenir maintenant qu'on utilise Qt :

Un objet avec des signaux et des slots

Qt rajoute des éléments appelés "Signaux" et "Slots" aux objets


Avant Qt, un objet était constitué d'attributs et de méthodes. C'est tout.
Qt rajoute en plus la possibilité d'utiliser ce qu'il appelle des signaux et des slots pour gérer les évènements.

Un signal est un message envoyé par l'objet (par exemple "on a cliqué sur le bouton").
Un slot est une... méthode. En fait, c'est une méthode classique comme toutes les autres, à la différence près qu'elle a le droit d'être connectée à un signal.

Avec Qt, on dit que l'on connecte des signaux et des slots entre eux. Supposons que vous ayez deux objets, chacun ayant ses propres attributs, méthodes, signaux et slots (je n'ai pas représenté les attributs et les méthodes sur mon schéma pour simplifier) :

Des signaux et des slots


Sur le schéma ci-dessus, on a connecté le signal 1 de l'objet 1 avec le slot 2 de l'objet 2.

Il est possible de connecter un signal à plusieurs slots. Ainsi, un clic sur un bouton pourrait appeler non pas une mais plusieurs méthodes. Attention, si un signal est connecté à plusieurs slots, il est impossible de prédire dans quel ordre Qt appellera les slots.

Comble du raffinement, il est aussi possible de connecter un signal à un autre signal. Le signal d'un bouton peut donc provoquer la création du signal d'un autre widget, qui peut à son tour appeler des slots (voire appeler d'autres signaux pour provoquer une réaction en chaîne !). C'est un peu particulier et on ne verra pas ça dans ce chapitre.

Connexion d'un signal à un slot simple

Voyons un cas très concret. Je vais prendre 2 objets, l'un de type QPushButton, et l'autre de type QApplication. Dans le schéma ci-dessous, ce que vous voyez sont de vrais signaux et slots que vous allez pouvoir utiliser :

Signaux et slots en pratique


Regardez attentivement ce schéma. Nous avons d'un côté notre bouton appelé "m_bouton" (de type QPushButton), et de l'autre notre application (de type QApplication, utilisé dans le main).

Nous voudrions par exemple connecter le signal "bouton cliqué" au slot "quitter l'application". Ainsi, un clic sur le bouton provoquerait l'arrêt de l'application.

Pour ce faire, nous devons utiliser une méthode statique de la classe QObject : connect().


Le principe de la méthode connect()



connect() est une méthode statique. Vous vous souvenez ce que ça veut dire ?
Une méthode statique est une méthode d'une classe que l'on peut appeler sans créer d'objet. C'est en fait exactement comme une fonction classique du langage C.

Si vous avez un trou de mémoire, allez vite relire le chapitre traitant des méthodes statiques !


Pour appeler une méthode statique, il faut faire précéder son nom du nom de la classe dans laquelle elle est déclarée. Comme connect() appartient à la classe QObject, il faut donc écrire :

Code : C++
1
QObject::connect();
Signaux et slots en pratique


La méthode connect prend 4 arguments :


Pour que vous puissiez vous repérer, j'ai remis ci-contre le schéma qu'on a vu un peu plus haut. Les couleurs sont les mêmes, cela devrait vous permettre de bien visualiser à quoi correspond chaque attribut.


Il existe aussi une méthode disconnect() permettant de casser la connexion entre 2 objets, mais on n'en parlera pas ici car on en a rarement besoin.

Utilisation de la méthode connect() pour quitter



Revenons au code, et plus précisément au constructeur de MaFenetre (fichier MaFenetre.cpp). Ajoutez cette ligne :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include "MaFenetre.h"
 
MaFenetre::MaFenetre() : QWidget()
{
    setFixedSize(300, 150);
 
    m_bouton = new QPushButton("Quitter", this);
    m_bouton->setFont(QFont("Comic Sans MS", 14));
    m_bouton->move(110, 50);
 
    // Connexion du clic du bouton à la fermeture de l'application
    QObject::connect(m_bouton, SIGNAL(clicked()), qApp, SLOT(quit()));
}

connect() est une méthode de la classe QObject. Comme notre classe MaFenetre hérite de QObject indirectement, elle possède elle aussi cette méthode. Cela signifie que dans ce cas, et dans ce cas uniquement, on peut enlever le préfixe QObject:: devant le connect() pour appeler la méthode statique.
J'ai choisi de conserver ce préfixe dans le cours pour rappeler qu'il s'agit d'une méthode statique, mais sachez donc qu'il n'a rien d'obligatoire si la méthode est appelée depuis une classe fille de QObject.


Etudions attentivement cette ligne et plus particulièrement les paramètres que l'on envoie à connect() :


Le slot quit() de notre objet de type QApplication est un slot prédéfini. Il en existe d'autres, comme aboutQt() qui affiche une fenêtre "A propos de Qt".
Parfois, pour ne pas dire souvent, les slots prédéfinis par Qt ne nous suffiront pas. Nous apprendrons dans la suite de ce chapitre à créer les nôtres.

Testons notre code ! La fenêtre qui s'ouvre est la suivante :

La fenêtre avec le bouton quitter


Rien de bien extraordinaire à première vue. Sauf que... si vous cliquez sur le bouton "Quitter", le programme s'arrête !
Hourra, on vient de réussir à connecter notre premier signal à un slot ! :D



Utilisation de la méthode connect() pour afficher "A propos"



On peut faire un autre essai pour se faire un peu plus la main si vous voulez. Je vous ai parlé d'un autre slot de QApplication : aboutQt().
Je vous propose de créer un second bouton qui se chargera d'afficher la fenêtre "A propos de Qt".

Je vous laisse rédiger le code tous seuls comme des grands.


...


...

C'est bon ?
Voici le code final :)

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include "MaFenetre.h"
 
MaFenetre::MaFenetre() : QWidget()
{
    setFixedSize(300, 150);
 
    m_quitter = new QPushButton("Quitter", this);
    m_quitter->setFont(QFont("Comic Sans MS", 14));
    m_quitter->move(110, 50);
    QObject::connect(m_quitter, SIGNAL(clicked()), qApp, SLOT(quit()));
 
    m_aPropos = new QPushButton("A propos", this);
    m_aPropos->setFont(QFont("Comic Sans MS", 14));
    m_aPropos->move(110, 90);
    QObject::connect(m_aPropos, SIGNAL(clicked()), qApp, SLOT(aboutQt()));
}


Vous noterez que j'ai pris la liberté de nommer les boutons avec des noms un peu plus compréhensibles.
Bien entendu, le fichier MaFenetre.h a un peu changé lui aussi du coup pour déclarer les attributs "m_quitter" et "m_aPropos", mais vous êtes assez grands pour le faire sans moi ;)

Le résultat est une fenêtre qui affiche 2 boutons :

Le bouton A propos


Le bouton "Quitter" ferme toujours l'application.
Quant à "A propos", il provoque l'ouverture de la fenêtre "A propos de Qt".

Le bouton A propos a ouvert une fenêtre

Des paramètres dans les signaux et slots

La méthode statique connect() est assez originale, vous l'avez vu. Il s'agit justement d'une des particularités de Qt que l'on ne retrouve pas dans les autres bibliothèques.
Ces autres bibliothèques, comme wxWidgets par exemple, utilisent à la place de nombreuses macros et se servent du mécanisme un peu complexe et délicat des pointeurs de fonction (pour indiquer l'adresse de la fonction à appeler en mémoire).

Il y a d'autres avantages à utiliser la méthode connect() avec Qt. On va ici découvrir que les signaux et les slots peuvent s'échanger des paramètres !


Dessin de la fenêtre



Dans un premier temps, nous allons placer de nouveaux widgets dans notre fenêtre.
Vous pouvez enlever les boutons, on ne va plus s'en servir ici.

A la place, je souhaite vous faire utiliser 2 nouveaux widgets :



On va aller un peu plus vite, je vous donne le code directement pour créer ça.
Tout d'abord, le header :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#ifndef DEF_MAFENETRE
#define DEF_MAFENETRE
 
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QLCDNumber>
#include <QSlider>
 
class MaFenetre : public QWidget
{
    public:
    MaFenetre();
 
    private:
    QLCDNumber *m_lcd;
    QSlider *m_slider; 
};
 
#endif


J'ai donc enlevé les boutons comme vous pouvez le voir, et rajouté un QLCDNumber et un QSlider.
Surtout, n'oubliez pas d'inclure le header de ces classes pour pouvoir les utiliser. J'ai gardé l'include du QPushButton ici, ça ne fait pas de mal de le laisser mais si vous ne comptez pas le réutiliser vous pouvez le virer sans crainte.

Et le fichier .cpp :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include "MaFenetre.h"
 
MaFenetre::MaFenetre() : QWidget()
{
    setFixedSize(200, 100);
 
    m_lcd = new QLCDNumber(this);
    m_lcd->setSegmentStyle(QLCDNumber::Flat);
    m_lcd->move(50, 20);
 
    m_slider = new QSlider(Qt::Horizontal, this);
    m_slider->setGeometry(10, 60, 150, 20);
}

Les détails ne sont pas très importants. J'ai modifié le type d'afficheur LCD pour qu'il soit plus lisible (avec setSegmentStyle). Quant au slider, j'ai rajouté un paramètre pour qu'il apparaisse horizontalement (sinon il est vertical).

Voilà qui est fait. Avec ce code, cette petite fenêtre devrait s'afficher :

Un afficheur LCD


Connexion avec des paramètres



Maintenant... connexiooooon !
C'est là que les choses deviennent intéressantes. On veut que l'afficheur LCD change de valeur en fonction de la position du curseur du slider.

On dispose du signal et du slot suivant :


La connexion se fait avec le code suivant :

Code : C++
1
QObject::connect(m_slider, SIGNAL(valueChanged(int)), m_lcd, SLOT(display(int)));


Bizarre n'est-ce pas ? :p
Il suffit d'indiquer le type du paramètre envoyé, ici un int, sans donner de nom à ce paramètre. Qt fait automatiquement la connexion entre le signal et le slot et "transmet" le paramètre au slot.

Le transfert de paramètre se fait comme ceci :

Connexion int à int


Ici il n'y a qu'un paramètre à transmettre, c'est donc simple. Sachez toutefois qu'il pourrait très bien y avoir plusieurs paramètres.

Le type des paramètres doivent correspondre absolument !
Vous ne pouvez pas connecter un signal qui envoie (int, double) à un slot qui reçoit (int, int). C'est un des avantages du mécanisme des signaux et des slots : il respecte le type des paramètres. Veillez donc à ce que les signatures soient identiques entre votre signal et votre slot.
En revanche, un signal peut envoyer plus de paramètres à un slot que celui-ci ne peut en recevoir. Dans ce cas, les paramètres supplémentaires seront ignorés.


Résultat : quand on change la valeur du slider, le LCD affiche la valeur correspondante !

Un afficheur LCD génère des évènements


Mais comment je sais moi quels sont les signaux et les slots que proposent chacune des classes ? Et aussi, comment je sais qu'un signal envoie un int en paramètre ?


La réponse devrait vous paraître simple les amis : la doc, la doc, la doc ! :D

Si vous regardez la documentation de la classe QLCDNumber, vous pouvez voir au début la liste de ses propriétés (attributs) et ses méthodes. Un peu plus bas, vous avez la liste des slots ("Public Slots") et des signaux ("Signals") qu'elle possède !

Les signaux et les slots sont hérités comme les attributs et méthodes. Et ça, c'est génial, bien qu'un peu déroutant au début.
Vous noterez donc qu'en plus des slots propres à QLCDNumber, celui-ci propose de nombreux autres slots qui ont été définis dans sa classe parente QWidget, et même des slots issus de QObject ! Vous pouvez par exemple lire :
  • 19 public slots inherited from QWidget
  • 1 public slot inherited from QObject

N'hésitez pas à consulter les slots (ou signaux) qui sont hérités des classes parentes. Parfois on va vous demander d'utiliser un signal ou un slot que vous ne verrez pas dans la page de documentation de la classe : vérifiez donc si celui-ci n'est pas défini dans une classe parente !


Exercice



Pour vous entraîner, je vous propose de réaliser une petite variation du code source précédent.
Au lieu d'afficher le nombre avec un QLCDNumber, affichez-le sous la forme d'une jolie barre de progression comme ceci :

Slider et progressbar


Je ne vous donne que 3 indications qui devraient vous suffire :


C'est tout. Bon courage :)

Créer ses propres signaux et slots

Voici maintenant une partie très intéressante, bien que plus délicate. Nous allons créer nos propres signaux et slots.

En effet, si en général les signaux et slots par défaut suffisent, il n'est pas rare que l'on se dise "Zut, le signal (ou le slot) dont j'ai besoin n'existe pas". C'est dans un cas comme celui-là qu'il devient indispensable de créer son widget personnalisé.

Pour pouvoir créer son propre signal ou slot dans une classe, il faut que celle-ci dérive directement ou indirectement de QObject. C'est le cas de notre classe MaFenetre : elle hérite de QWidget, qui hérite de QObject. On a donc le droit de créer des signaux et des slots dans MaFenetre.


Nous allons commencer par créer notre propre slot, puis nous verrons comment créer notre propre signal.


Créer son propre slot



Je vous rappelle tout d'abord qu'un slot n'est rien d'autre qu'une méthode que l'on peut connecter à un signal.
Nous allons donc créer une méthode, mais en suivant quelques règles un peu particulières...

Le but du jeu



Pour nous entraîner, nous allons inventer un cas où le slot dont on a besoin n'existe pas.
Je vous propose de conserver le QSlider (je l'aime bien celui-là :D ) et de ne garder que ça sur la fenêtre. Nous allons faire en sorte que le QSlider contrôle la largeur de la fenêtre.

Votre fenêtre doit ressembler à cela :

Fenêtre avec slider


Nous voulons que le signal valueChanged(int) du QSlider puisse être connecté à un slot de notre fenêtre (de type MaFenetre). Ce nouveau slot aura pour rôle de modifier la largeur de la fenêtre.
Comme il n'existe pas de slot "changerLargeur" dans la classe QWidget, nous allons devoir le créer.

Pour créer ce slot, il va falloir modifier un peu notre classe MaFenetre. Commençons par le header.

Le header (MaFenetre.h)



Dès que l'on doit créer un signal ou un slot personnalisé, il est nécessaire de définir une macro dans le header de la classe.

Cette macro porte le nom de Q_OBJECT (tout en majuscules) et doit être placée tout au début de la déclaration de la classe :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class MaFenetre : public QWidget
{
    Q_OBJECT
 
    public:
    MaFenetre();
 
    private:
    QSlider *m_slider;
};


Pour le moment, notre classe ne définit qu'un attribut (le QSlider, privé) et une méthode (le constructeur, public).

La macro Q_OBJECT "prépare" en quelque sorte le compilateur à accepter un nouveau mot-clé : "slot". Nous allons maintenant pouvoir créer une section "slots", comme ceci :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class MaFenetre : public QWidget
{
    Q_OBJECT
 
    public:
    MaFenetre();
 
    public slots:
    void changerLargeur(int largeur);
 
    private:
    QSlider *m_slider;
};


Vous noterez la nouvelle section "public slots". Je rends toujours mes slots publics. On peut aussi les mettre privés mais ils seront quand même accessibles de l'extérieur car Qt a besoin de pouvoir appeler un slot depuis n'importe quel autre widget.

A part ça, le prototype de notre slot-méthode est tout à fait classique. Il ne nous reste plus qu'à l'implémenter dans le .cpp.


L'implémentation (MaFenetre.cpp)



L'implémentation est d'une simplicité redoutable. Regardez :

Code : C++
1
2
3
4
void MaFenetre::changerLargeur(int largeur)
{
    setFixedSize(largeur, 100);
}


Le slot prend en paramètre un entier : la nouvelle largeur de la fenêtre.
Il se contente d'appeler la méthode setFixedSize de la fenêtre et de lui envoyer la nouvelle largeur qu'il a reçue.


Connexion



Bien, voilà qui est fait. Enfin presque : il faut encore connecter notre QSlider au slot de notre fenêtre. Où va-t-on faire ça ? Dans le constructeur de la fenêtre (toujours dans MaFenetre.cpp) :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
MaFenetre::MaFenetre() : QWidget()
{
    setFixedSize(200, 100);
 
    m_slider = new QSlider(Qt::Horizontal, this);
    m_slider->setRange(200, 600);
    m_slider->setGeometry(10, 60, 150, 20);
 
    QObject::connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(changerLargeur(int)));
}


J'ai volontairement modifié les différentes valeurs que peut prendre notre slider pour le limiter entre 200 et 600 avec la méthode setRange(). Ainsi, on est sûr que notre fenêtre ne pourra ni être plus petite que 200 pixels de largeur, ni être plus grande que 600 pixels de largeur.

La connexion se fait entre le signal valueChanged(int) de notre QSlider, et le slot changerLargeur(int) de notre classe MaFenetre. Vous voyez là encore un exemple où this est indispensable : il faut pouvoir indiquer un pointeur vers l'objet actuel (la fenêtre) et seul this peut faire ça !

Schématiquement, on a réalisé la connexion suivante :

Connexion entre le slider et la fenêtre


Compilation



Avec toutes les nouveautés que nous venons d'utiliser par rapport au C++, la compilation par un make ne suffira pas.

Je vous avais dit qu'il fallait refaire un qmake à chaque fois que les fichiers du projet changeaient. En fait j'ai un peu menti :p
Comme vous utilisez la macro Q_OBJECT, Qt a besoin d'appeler un pré-compilateur qui lui est propre appelé le moc (Meta-Object Compiler).

Rassurez-vous, vous n'avez rien à faire de spécial. Relancez juste un qmake avant de faire votre make, et Qt fera le travail de "traduction" du slot en quelque chose de compréhensible pour le compilateur C++.
Vous noterez que le qmake a provoqué la création d'un fichier intermédiaire moc_MaFenetre.cpp, ce qui est parfaitement normal. Ce fichier fournit des informations indispensables au compilateur.

Vous pouvez ensuite faire un make, la compilation devrait bien se passer.

Souvenez-vous ! Si jamais lors de la compilation vous rencontrez l'erreur suivante :
undefined reference to 'vtable for MaFenetre'
... cela signifie que vous n'avez pas fait de qmake avant. Si le moc ne s'est pas exécuté auparavant, la compilation échouera.


Vous pouvez enfin admirer le résultat. Ouf ! :)

Le slider élargit la fenêtre


Amusez-vous à redimensionner la fenêtre comme bon vous semblera avec le slider. Comme nous avons fixé les limites du slider entre 200 et 600, la largeur de la fenêtre restera comprise entre 200 et 600 pixels.


Exercice : redimensionner la fenêtre en hauteur



Voici un petit exercice, mais qui va vous forcer à travailler (bande de fainéants, vous me regardez faire depuis tout à l'heure :p ).
Je vous propose de créer un second QSlider, vertical cette fois, qui contrôlera la hauteur de la fenêtre. Pensez à bien définir des limites appropriées pour les valeurs de ce nouveau slider.

Vous devriez obtenir un résultat qui ressemblera à ça :

Un slider vertical


Si vous voulez "conserver" la largeur pendant que vous modifiez la hauteur, et inversement, vous aurez besoin d'utiliser les méthodes accesseur width() (largeur actuelle) et height() (hauteur actuelle).
Vous comprendrez très certainement l'intérêt de ces informations lorsque vous coderez. Au boulot !


Créer son propre signal



Il est plus rare d'avoir à créer son signal que son slot, mais cela peut arriver.

Je vous propose de réaliser le programme suivant : si le slider horizontal arrive à sa valeur maximale (600 dans notre cas), alors on émet un signal "agrandissementMax". Notre fenêtre doit pouvoir émettre l'information comme quoi elle est agrandie au maximum.
Après, nous connecterons ce signal à un slot pour vérifier que notre programme réagit correctement.


Le header (MaFenetre.h)



Commençons par changer le header :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class MaFenetre : public QWidget
{
    Q_OBJECT
 
    public:
    MaFenetre();
 
    public slots:
    void changerLargeur(int largeur);
 
    signals:
    void agrandissementMax();
 
    private:
    QSlider *m_slider;
};


On a ajouté une section "signals". Les signaux se présentent en pratique sous forme de méthodes (comme les slots) à la différence près qu'on ne les implémente pas dans le .cpp. En effet, c'est Qt qui le fait pour nous. Si vous tentez d'implémenter un signal, vous aurez une erreur du genre "Multiple definition of...".

Un signal peut passer un ou plusieurs paramètres. Dans notre cas, il n'en envoie aucun.
Un signal doit toujours renvoyer void.


L'implémentation (MaFenetre.cpp)



Maintenant que notre signal est défini, il faut que notre classe puisse l'émettre à un moment.
Quand est-ce qu'on sait que la fenêtre a été agrandie au maximum ? Dans le slot changerLargeur ! Il suffit de tester dans ce slot si la largeur correspond au maximum (600), et d'émettre alors le signal "Youhou, j'ai été agrandie au maximum !".

Retournons dans MaFenetre.cpp et implémentons ce test qui émet le signal depuis changerLargeur :

Code : C++
1
2
3
4
5
6
7
8
9
void MaFenetre::changerLargeur(int largeur)
{
    setFixedSize(largeur, height());
 
    if (largeur == 600)
    {
        emit agrandissementMax();
    }
}


Notre méthode s'occupe toujours de redimensionner la fenêtre, mais vérifie en plus si la largeur a atteint le maximum (600). Si c'est le cas, elle émet le signal agrandissementMax().
Pour émettre un signal, on utilise le mot-clé emit, là encore un terme inventé par Qt qui n'existe pas en C++. L'avantage est que c'est très lisible, on comprend "Emettre le signal agrandissementMax()".

Ici, notre signal n'envoie pas de paramètres. Toutefois, sachez que si vous voulez envoyer un paramètre c'est très simple. Il suffit d'appeler votre signal comme ceci : emit monSignal(parametre1, parametre2, ...);


Connexion



Il ne nous reste plus qu'à connecter notre nouveau signal à un slot. Vous pouvez connecter ce signal au slot que vous voulez. Personnellement, je propose de le connecter à l'application (à l'aide du pointeur global qApp) pour provoquer l'arrêt du programme.
Ca n'a pas trop de sens je suis d'accord, mais c'est juste pour s'entraîner et vérifier que ça fonctionne. Vous aurez l'occasion de faire des connexions plus logiques plus tard, je ne m'en fais pas pour ça ;)

Dans le constructeur de MaFenetre, je rajoute donc :

Code : C++
1
QObject::connect(this, SIGNAL(agrandissementMax()), qApp, SLOT(quit()));


Vous pouvez tester le résultat : normalement le programme s'arrête quand la fenêtre est agrandie au maximum.

Le schéma des signaux qu'on vient d'émettre et connecter est le suivant :

Echange de signaux entre objets


Dans l'ordre, voici ce qui s'est passé :

  1. Le signal valueChanged du slider a appelé le slot changerLargeur de la fenêtre.
  2. Le slot a fait ce qu'il avait à faire (changer la largeur de la fenêtre) et a vérifié si la fenêtre était arrivée à sa taille maximale. Lorsque cela a été le cas, le signal personnalisé agrandissementMax() a été émis.
  3. Le signal agrandissementMax() de la fenêtre était connecté au slot quit() de l'application, ce qui a provoqué la fermeture du programme.

Et voilà comment le déplacement du slider peut, par réaction en chaîne, provoquer la fermeture du programme !
Bien entendu, ce schéma peut être aménagé et complexifié selon les besoins de votre application.

Maintenant que vous savez créer vos propres slots et signaux, vous avez toute la souplesse nécessaire pour faire ce que vous voulez ! :D

Q.C.M.

Laquelle de ces notions n'existe pas normalement en C++ ?
Peut-on connecter un signal à plusieurs slots ?
Les signaux et les slots sont-ils hérités ?
Quelles conditions doivent être remplies pour que l'on puisse définir un signal ou un slot personnalisé dans une classe ?
Comment émet-on un signal ?

Statistiques de réponses au QCM


Eh ben dites donc les amis, que de nouveautés dans ce chapitre décidément !

Les signaux et les slots, c'est vraiment ce qui fait la force de Qt... mais ses détracteurs disent que c'est une erreur d'avoir voulu "modifier" le langage C++. En effet, la compilation est plus lourde car il y a des étapes de pré-compilation à effectuer impérativement si on veut que le code soit compilable. C'est un point de vue qui se défend.

L'avantage de ce système, et ça personne ne le discute, c'est qu'il est robuste. On dispose d'une extraordinaire souplesse pour faire communiquer des objets entre eux :


Les autres bibliothèques, comme wxWidgets, utilisent un ensemble de macros, moins lisibles mais qui ne nécessitent pas l'utilisation d'outils intermédiaires comme le moc.

Bref, profitez à fond des signaux et des slots, avec ça vous pouvez vraiment faire ce que vous voulez :D
Chapitre précédent Sommaire Chapitre suivant
Retour en haut Retour en haut


Créé : le 18/09/2007 à 17:13:58
Modifié : le 23/10/2008 à 14:17:50
Avancement : 100%
Licence : Copie non autorisée

21 commentaires

Changer de design | En savoir plus | Plan du site | Politique d'accessibilité | Règles | RSS tutoriels | RSS news
Édité par Simple IT SARL : Nous contacter | Notre blog | Revue de presse | Publicité

Y'a plus rien à lire, faut remonter maintenant !

Hébergement web - Correction de tutoriels - Créer un site
Vous souhaitez apparaître ici ? Contactez-nous.

Nombre de connectés 91 Zéros connectés | Requêtes SQL 8 requêtes | Temps de génération de la page : Total (SQL) 0.0362s (0.019s)