Cours:SignalSlotQT : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
(clignotement avec QTimer)
(principe)
 
(Une révision intermédiaire par le même utilisateur non affichée)
Ligne 83 : Ligne 83 :
 
Nous avons précédemment fait cette connexion graphiquement dans qtDesigner, ici nous allons utiliser la fonction {{Rouge|connect}}.
 
Nous avons précédemment fait cette connexion graphiquement dans qtDesigner, ici nous allons utiliser la fonction {{Rouge|connect}}.
 
<source lang=cpp>
 
<source lang=cpp>
connect(&objetEmetteur,SIGNAL(signalEmis()),&objetRecepteur,SLOT(slotToExecute()));
+
connect(&objetEmetteur,&ClasseObjetEmetteur::signalEmis,&objetRecepteur,&ClasseObjetRecepteur::slotToExecute);
 
</source>
 
</source>
  
Ligne 95 : Ligne 95 :
 
     // on ajoute ici les connexions
 
     // on ajoute ici les connexions
 
     // objet vers mainwindow
 
     // objet vers mainwindow
     connect(&obj1,SIGNAL(....),this,SLOT(....));
+
     connect(&obj,&ClasseObjetEmetteur::signalEmis,this,&MainWindow::monSlot);
 
     // mainwindow vers objet
 
     // mainwindow vers objet
     connect(this,SIGNAL(....),&obj1, SLOT(....));
+
     connect(this,&MainWindow::monSignal,&obj,&ClasseObjetRecepteur::slotToExecute);
 
     // ou d'un objet graphique vers un objet de la nouvelle classe
 
     // ou d'un objet graphique vers un objet de la nouvelle classe
     connect(ui->pushButton,SIGNAL(....),&obj1,SLOT(...));
+
     connect(ui->pushButton,&ClasseObjetRecepteur::signalEmis,&obj,&ClasseObjetRecepteur::nomDuSlot);
 
}
 
}
 
</source>
 
</source>
Ligne 147 : Ligne 147 :
  
 
On peut facilement faire clignoter une lampe avec un QTimer :
 
On peut facilement faire clignoter une lampe avec un QTimer :
*on choisit une durée : monTimer.setInterval(dure_Ms);
+
*on choisit une durée : {{Rouge|monTimer.setInterval(dure_Ms);}}
*le signal timeout est émis toutes les duree_Ms
+
*le {{Rouge|signal timeout}} est émis toutes les duree_Ms
 
*il faut se connecter sur le signal : <br>
 
*il faut se connecter sur le signal : <br>
 
<source lang=cpp>
 
<source lang=cpp>
Ligne 154 : Ligne 154 :
 
         &maLampe,&Lampe::toggle);
 
         &maLampe,&Lampe::toggle);
 
</source>
 
</source>
*on lance le timer : monTimer.start();
+
*on lance le timer : {{Rouge|monTimer.start();}}
  
 
Il faut bien entendu ajouter monTimer comme un attribut de la classe MainWindow (ajouter #include <QTimer>)
 
Il faut bien entendu ajouter monTimer comme un attribut de la classe MainWindow (ajouter #include <QTimer>)

Version actuelle datée du 20 septembre 2024 à 16:58

Retour à la liste des Tds

Au besoin, la documentation QT peut-être intéressante : http://doc.qt.io/qt-5/signalsandslots.html

spécialisation de la classe QObject

Principe :

  • créer nouvelle classe
  • nom de la classe : MaClasse (respecter la casse : ! les capitales au bon endroit ! )
  • Base class : QObject
  • terminé !
// fichier dans lequel est déclaré la classe QObject
#include <QObject>

// on hérite de la classe QObject
class MaClasse : public QObject
{
// mot clé pour que qmake fasse son job pour les signaux/slots notamment
    Q_OBJECT
public:
// constructeur de la classe :
// le "explicit" empêche de faire des conversions bizarroïdes entre classes
// ce n'est pas à retenir
    explicit MaClasse(QObject *parent = nullptr);

signals:

public slots:
};

une classe utile :

On va faire une classe Lampe :

  • elle aura un attribut privé : isAllume de type bool
  • des slots (en gros le nom des méthodes sur QT) dont les prototypes sont :
    • void allumer()
    • void eteindre()
    • void changerEtat()
  • un signal
    • il suffit de rajouter le signal dans la déclaration de la classe (header file), rien dans le cpp !
    • on ajoute dans la partie signals:
    • void valueChanged(int newValue);
    • lorsque c'est nécessaire on envoie la nouvelle valeur de la façon suivante :
    • emit valueChanged(valeur);
    • il faut bien entendu remplacer valeur par un truc intéressant !

Remarque : vous pouvez laisser de côté changerEtat pour le moment.

Utilisation de la classe

ajouter un attribut dans la classe MainWindow

Pour ajouter un objet de notre nouvelle classe, on doit bien entendu ajouter sa définition à l'endroit où on souhaite l'utiliser :

#include "maclasse.h"

On va ensuite ajouter dans la classe MainWindow un attribut (ou plusieurs), de préférence privé :

....
class MainWindow : public ....
{
....
private :
  MaClasse obj1;
  MaClasse obj2;
...
}

relier signal avec slot

Il faut maintenant utiliser cet objet.

principe

Pour utiliser ce nouvel objet, on doit connecter des signaux et des slots.

Nous avons précédemment fait cette connexion graphiquement dans qtDesigner, ici nous allons utiliser la fonction connect.

connect(&objetEmetteur,&ClasseObjetEmetteur::signalEmis,&objetRecepteur,&ClasseObjetRecepteur::slotToExecute);

Les connections seront mises en place dans le constructeur de la classe MainWindow, à la fin du constructeur et après la mise en place de l'interface graphique :

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent), ui(new Ui::MainWindow)
{
    // mise en place de l'interface graphique
    ui->setupUi(this);
    // on ajoute ici les connexions
    // objet vers mainwindow
    connect(&obj,&ClasseObjetEmetteur::signalEmis,this,&MainWindow::monSlot);
    // mainwindow vers objet
    connect(this,&MainWindow::monSignal,&obj,&ClasseObjetRecepteur::slotToExecute);
    // ou d'un objet graphique vers un objet de la nouvelle classe
    connect(ui->pushButton,&ClasseObjetRecepteur::signalEmis,&obj,&ClasseObjetRecepteur::nomDuSlot);
}

afficher un message

Si ce n'est pas encore fait, ajouter dans un premier temps un affichage avec qDebug() dans vos méthodes allumer et éteindre.

Placer 2 boutons sur l'écran, et connecter ensuite les boutons sur les 2 méthodes allumer() et eteindre()

Question.jpg Vérifier le fonctionnement

Si ça fonctionne, on peut supprimer les qDebug() dans la classe Lampe. Ajouter ensuite un nouveau SLOT dans la classe MainWindow, qui sera connecté sur le signal valueChanged(valeur) de la classe lampe.

Ce SLOT affichera sur la console,à l'aide d'un qDebug(), l'état de la lampe.

Question.jpg Faire ces modifications

changer couleur d'un bouton

On souhaite maintenant utiliser 1 bouton pour visualiser l'état de la lampe : le bouton sera rouge ou noir suivant si la lampe est allumée ou non.

On écrira donc un nouveau SLOT (on conserve le SLOT qui permet d'afficher dans la console tel quel) qui changera la couleur du bouton.

Ce SLOT sera également connecté sur le signal valueChanged(valeur) : On peut connecter plusieurs SLOTs sur le même SIGNAL

Question.jpg Mettre en place cette visualisation


Remarque : pour différencier les boutons permettant de visualiser l'état des lampes des boutons à cliquer, on peut arrondir les angles des boutons, par ex :

ui->pushButton->setStyleSheet(QString::fromUtf8("background-color: red;"
                                                "border-style: solid;"
                                                "border-color: black;"
                                                "border-width: 2px;"
                                                "border-radius: 50px;")
                             );
// !! attention la valeur de "border-radius" doit être plus petite que la moitié de la longueur du plus petit côté du bouton

Plusieurs lampes

Question.jpg Ajouter plusieurs boutons, lampes, bouton pour changer l'état ...

clignotement avec QTimer

On peut facilement faire clignoter une lampe avec un QTimer :

  • on choisit une durée : monTimer.setInterval(dure_Ms);
  • le signal timeout est émis toutes les duree_Ms
  • il faut se connecter sur le signal :
connect(&monTimer,&QTimer::timeout,
        &maLampe,&Lampe::toggle);
  • on lance le timer : monTimer.start();

Il faut bien entendu ajouter monTimer comme un attribut de la classe MainWindow (ajouter #include <QTimer>)