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.
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)
Salut,
J'y jetterais un oeil ce soir, ça n'a pas l'air impossible à faire.
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; }
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.
Renvoit:
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; }
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.
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
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
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)
Ok, j'essaierai de rédiger tout ça un peu plus clairement au passage.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager