IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Discussion :

Lier les signal/slot de Qt à boost::signal


Sujet :

Qt

  1. #1
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut Lier les signal/slot de Qt à boost::signal
    Bonjour à tous.
    Savez vous s'il existe un moyen de lier boost::signal au mécanisme de signal/slot proposé par Qt ?
    Pour le moment je google, mais rien de bien tangible.

    Merci.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  2. #2
    Membre expert

    Avatar de IrmatDen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 727
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 727
    Points : 3 266
    Points
    3 266
    Par défaut
    Salut,

    J'y jetterais un oeil ce soir, ça n'a pas l'air impossible à faire.

  3. #3
    Membre expert

    Avatar de IrmatDen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 727
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 727
    Points : 3 266
    Points
    3 266
    Par défaut
    Désolé de la réponse tardive, je me suis dit que j'allais en profiter pour passer à boost 1.35

    Donc, voilà un code illustrant les 2 possibilités suivantes:
    • utilisation d'un boost.signals connecté à un slot Qt
    • utilisation d'un boost.signals connecté à un signal Qt (enfin, pas vraiment => obligation de passer par une fonction assurant le relais dû à la visibilité des signaux Qt)


    Et 2 notes importantes:
    • les include des fichiers boost doivent être avant ceux de Qt où tu auras un petit paquet d'erreur de compil (Qt utilise un #define sur signals, donc forcément ça perturbe grave boost.signals... et comme tu ne peux pas forcément utiliser #undef, en tout cas, pas ici).
    • Garde en tête qu'utiliser un signal boost pour invoquer un slot Qt ne permet en aucun cas d'utiliser la méthode sender() puisque les infos de Metaobject ne nous sont pas dispo. Le pointeur renvoyé sera donc nul. (Enfin, pas vraiment surprenant, c'est comme si tu appeler toi même le slot, mais je préfère le signaler pour éviter tout dommage collatéral )


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    #include <boost/signal.hpp>
    #include <boost/bind.hpp>
     
    #include <QtCore>
     
    #include <iostream>
     
    //----------------------------------------------------------
    // Partie Qt
    //----------------------------------------------------------
     
    class QtClass : public QObject
    {
    Q_OBJECT
     
    public:
        QtClass()
        {
            connect(this, SIGNAL(qtSignal(float)), this, SLOT(qtSlot(float)));
        }
     
        // OBLIGATOIRE si on veut connecter un signal boost à un signal Qt: les signaux sont des méthodes protected
        void triggerQtSignalEmission(float x)
        {
            emit qtSignal(x);
        }
     
    public slots:
        void qtSlot(float x)
        {
            QObject *s = sender();
            if(s == this)
                std::cout << "From internal connection:" << std::endl;
            else if(!s)
                std::cout << "Unknown sender:" << std::endl;
            std::cout << "In QtClass::qtSlot(), x=" << x << std::endl;
        }
     
    signals:
        void qtSignal(float);
    };
     
     
    // Nécessaire dû à l'utilisation de la macro Q_OBJECT dans QtClass
    #include "main.moc"
     
    //----------------------------------------------------------
    // Partie non Qt
    //----------------------------------------------------------
     
    class NonQtClass
    {
    public:
        void boostSignalToQtSlot(QtClass *qc)
        {
            boost::signal<void (float)> sig;
            sig.connect(boost::bind(&QtClass::qtSlot, qc, _1));
            sig(3.14);
        }
     
        void boostSignalToQtSignal(QtClass *qc)
        {
            boost::signal<void (float)> sig;
            sig.connect(boost::bind(&QtClass::triggerQtSignalEmission, qc, _1));
            sig(42.0);
        }
    };
     
    int main(int argc, char **argv)
    {
        NonQtClass nqc;
        QtClass    qc;
     
        // Déclenche un boost::signal attaché à un slot Qt:
        nqc.boostSignalToQtSlot(&qc);
     
        // Déclenche un boost::signal lié à l'émission d'un signal Qt
        // (on triche par l'utilisation d'une méthode intermédiaire obligatoire)
        nqc.boostSignalToQtSignal(&qc);
     
        return 0;
    }

  4. #4
    Membre expert

    Avatar de IrmatDen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 727
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 727
    Points : 3 266
    Points
    3 266
    Par défaut
    Je viens d'ajouter les connexions signal Qt -> fonctions standard, juste pour compléter l'illustration. Le principal élément est l'apparition de la classe QtSlotToStandardCPPBridge pour faire le pont entre un signal Qt et un signal boost.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    #include <boost/signal.hpp>
    #include <boost/bind.hpp>
     
    #include <QtCore>
     
    #include <iostream>
    #include <cmath>
     
    //----------------------------------------------------------
    // Partie Qt
    //----------------------------------------------------------
     
    class QtClass : public QObject
    {
    Q_OBJECT
     
    public:
        QtClass()
        {
            connect(this, SIGNAL(qtSignal(float)), this, SLOT(qtSlot(float)));
        }
     
        // OBLIGATOIRE si on veut connecter un signal boost à un signal Qt: les signaux sont **protégés**
        void triggerQtSignalEmission(float x)
        {
            emit qtSignal(x);
        }
     
    public slots:
        void qtSlot(float x)
        {
            QObject *s = sender();
            if(s == this)
                std::cout << "From internal connection:" << std::endl;
            else if(!s)
                std::cout << "Unknown sender:" << std::endl;
            std::cout << "In QtClass::qtSlot(), x=" << x << std::endl;
        }
     
    signals:
        void qtSignal(float);
    };
     
    //----------------------------------------------------------
    // Adapteur Qt
    //----------------------------------------------------------
     
    class QtSignalToStandardCPPBridge : public QObject
    {
    Q_OBJECT
     
    public:
        QtSignalToStandardCPPBridge(QtClass *qc)
        {
            connect(qc, SIGNAL(qtSignal(float)), this, SLOT(onQtSignalEmitted(float)));
        }
     
        template<typename Signature>
        void addStandardSlot(Signature fun)
        {
            sig.connect(fun);
        }
     
    private slots:
        void onQtSignalEmitted(float x)
        {
            sig(x);
        }
     
    private:
        boost::signal<void (float)>sig;
    };
     
    // Nécessaire dû à l'utilisation des macros Q_OBJECT dans QtClass et QtToBoostBridge
    #include "main.moc"
     
    //----------------------------------------------------------
    // Partie non Qt
    //----------------------------------------------------------
     
    class NonQtClass
    {
    public:
        // fonction normale que l'on appelera depuis un signal Qt en passant par un pont
        void normalFunction(float x)
        {
            std::cout << "In NonQtClass::normalFunction(), x=" << x << std::endl;
        }
     
        // Et une autre pour le fun
        void displaySquareRoot(float x)
        {
            std::cout << "In NonQtClass::displaySquareRoot(), sqrt(x)=" << std::sqrt(x) << std::endl;
        }
     
    public:
        void boostSignalToQtSlot(QtClass *qc)
        {
            boost::signal<void (float)> sig;
            sig.connect(boost::bind(&QtClass::qtSlot, qc, _1));
            sig(3.14f);
        }
     
        void boostSignalToQtSignal(QtClass *qc)
        {
            boost::signal<void (float)> sig;
            sig.connect(boost::bind(&QtClass::triggerQtSignalEmission, qc, _1));
            sig(42.0f);
        }
     
        void QtSignalToStandardFunction(QtClass *qc)
        {
            QtSignalToStandardCPPBridge adapter(qc);
            adapter.addStandardSlot(boost::bind(&NonQtClass::normalFunction, this, _1));
            adapter.addStandardSlot(boost::bind(&NonQtClass::displaySquareRoot, this, _1));
            // On déclenche ici manuellement l'émission du signal Qt
            qc->triggerQtSignalEmission(121.0f);
        }
    };
     
    int main(int argc, char **argv)
    {
        NonQtClass nqc;
        QtClass         qc;
     
        // Déclenche un boost::signal attaché à un slot Qt:
        nqc.boostSignalToQtSlot(&qc);
     
        // Déclenche un boost::signal lié à l'émission d'un signal Qt
        // (on triche par l'utilisation d'une méthode intermédiaire obligatoire)
        nqc.boostSignalToQtSignal(&qc);
     
        nqc.QtSignalToStandardFunction(&qc);
     
        return 0;
    }
    Renvoit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Unknown sender:
    In QtClass::qtSlot(), x=3.14
    From internal connection:
    In QtClass::qtSlot(), x=42
    From internal connection:
    In QtClass::qtSlot(), x=121
    In NonQtClass::normalFunction(), x=121
    In NonQtClass::displaySquareRoot(), sqrt(x)=11
    Bien sûr, le code est loin d'être d'une propreté exemplaire, mais ça devrait illustrer l'utilisation conjointe de Boost.signals aux signaux/slots Qt.


    edit:
    Petite précision, juste en cas, pense à activer la console dans ton fichier pro pour voir la sortie ("CONFIG += console"), et à le lancer depuis une console

  5. #5
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Merci merci merci !!!!
    J'imaginais quelque chose de cette forme, mais je n'ai pas le niveau pour le réaliser.

    PS : Ce code doit être dans la FAQ.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message
    Merci merci merci !!!!
    J'imaginais quelque chose de cette forme, mais je n'ai pas le niveau pour le réaliser.

    PS : Ce code doit être dans la FAQ.
    Si un de vous deux veut bien la faire

  7. #7
    Membre expert

    Avatar de IrmatDen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 727
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 727
    Points : 3 266
    Points
    3 266
    Par défaut
    Ok, j'essaierai de rédiger tout ça un peu plus clairement au passage.

  8. #8
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par IrmatDen Voir le message
    Ok, j'essaierai de rédiger tout ça un peu plus clairement au passage.
    Cool

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Interaction entre boost.signals et les signaux/slots Qt
    Par dourouc05 dans le forum Téléchargez
    Réponses: 0
    Dernier message: 01/11/2010, 22h30
  2. Signal/Slot : Quand ne pas les utiliser ?
    Par Mendahor dans le forum Qt
    Réponses: 1
    Dernier message: 27/02/2010, 13h15
  3. [boost::signal] declencher un signal dans un slot
    Par hushhush dans le forum Boost
    Réponses: 2
    Dernier message: 18/11/2009, 00h11
  4. Signals slots boost/libsigc++/Qt
    Par epsilon68 dans le forum Qt
    Réponses: 14
    Dernier message: 10/08/2006, 21h31

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo