Allegro.cc - Online Community

Allegro.cc Forums » Off-Topic Ordeals » Qt's signals and slots mechanism: not very good?

This thread is locked; no one can reply to it. rss feed Print
Qt's signals and slots mechanism: not very good?
axilmar
Member #1,204
April 2001

Qt's signals & slots mechanism is of dubious usefulness, to say the least. In the current project I am working on, I had to use the MOC compiler manually (old Qt version, IDE does not support integration with this old Qt version), and it's very cumbersome to do so every time there is a change in the design of the software. And Qt does not throw an exception if a slot is wrongly connected to a signal, it only outputs a debug message, so one has to be very careful about what happens.

I decided that I've had enough with it, and I've coded my own Slot classes, which are templates. Here is the code for a slot with 1 parameter:

1/** base class for Qt slots with 1 parameter.
2 */
3template <class T1> class QSlot1 : public QObject {
4public:
5 /** the default constructor.
6 @param parent parent object.
7 */
8 QSlot1(QObject *parent) : QObject(parent) {
9 }
10 
11 /** returns the meta object of the QObject.
12 @return the meta object of the QObject.
13 */
14 virtual QMetaObject *metaObject() const {
15 return staticMetaObject();
16 }
17 
18 /** invokes the one and only method 'operator ()()'.
19 */
20 virtual bool qt_invoke(int id, QUObject *o) {
21 switch ( id - staticMetaObject()->slotOffset() ) {
22 case 0:
23 operator ()((T1)GetQUType<T1>::get().get(o + 1));
24 break;
25
26 default:
27 return QObject::qt_invoke(id, o);
28 }
29
30 return TRUE;
31 }
32
33 /** returns the slot's name.
34 @return the slot's name.
35 */
36 static QCString name() {
37 static const QCString n = QCString().sprintf("operator()(%s)", GetQUType<T1>::get().desc());
38 return n;
39 }
40 
41 /** returns the slot's name prefixed with the appropriate value used for macro SLOT.
42 @return the slot's name prefixed with the appropriate value used for macro SLOT.
43 */
44 static QCString connectName() {
45 static const QCString n = "1" + name();
46 return n;
47 }
48 
49 /** the slot interface.
50 */
51 virtual void operator ()(T1 t1) const = 0;
52
53private:
54 /* returns the static meta object.
55 @return pointer to the static meta object.
56 */
57 static QMetaObject *staticMetaObject() {
58 static QMetaObjectCleanUp cleanUp_Test;
59 static QMetaObject *metaObject = NULL;
60
61 //if the metaobject is already created, return it
62 if (metaObject) return metaObject;
63 
64 //the parent meta object
65 QMetaObject* parentMetaObject = QObject::staticMetaObject();
66
67 //parameter 1
68 static const QUParameter param[] = {
69 {"t1", &GetQUType<T1>::get(), 0, QUParameter::In}
70 };
71
72 //the one and only slot
73 static const QUMethod slot = {"operator()", 1, param};
74
75 //the table of slots
76 static const QMetaData slot_tbl[] = {
77 {name(), &slot, QMetaData::Public}
78 };
79
80 //create the meta object
81 metaObject = QMetaObject::new_metaobject(
82 "QSlot1", parentMetaObject,
83 slot_tbl, 1,
84 0, 0,
85 0, 0,
86 0, 0,
87 0, 0);
88
89 //delete the meta object at program exit
90 cleanUp_Test.setMetaObject(metaObject);
91
92 //return the new meta object
93 return metaObject;
94 }
95};

It works like a charm: I can write the following code (for example):

connect(button, SIGNAL(clicked()), myObject, &MyObject::method);

So why Trolltech does not provide these classes? for me, it's for economic reasons, i.e. forcing people to buy new licenses in order to get integration with newer environments. There is no technical problem in using signals with slot classes.

juvinious
Member #5,145
October 2004
avatar

Attached is what I use for my GUI lib, I modified the version that is from here.

I cleaned up some of the code that had issues and added in signal chaining.

So to use for one signal like you did above would be like:

1 
2struct obj : public has_slots<>
3{
4 void stuff(int i){ // do something with i }
5}
6 
7obj myObj;
8 
9sigslot::signal1<int> mySignal;
10 
11 
12mySignal.connect(&myObj,&obj::stuff);
13 
14...
15 
16mySignal.emit(23);
17 
18// You can also chain signals
19 
20sigslot::signal1<int> mySig2;
21 
22mySig2.connect(&myObj,&obj::stuff);
23 
24mySignal.connect(&mySig2);
25 
26// Will actually run stuff twice since it's connected to two slots
27mySignal.emit(55);

__________________________________________
Paintown

Jonny Cook
Member #4,055
November 2003

I never found it that annoying. Qts method is a lot more flexible, and will work with an arbitrary amount of arguments. And you can also do cool things like have it auto connect methods with certain names.

The face of a child can say it all, especially the mouth part of the face.

axilmar
Member #1,204
April 2001

Quote:

I never found it that annoying.

Neither did I when I used VS6 which Qt integrated with nicely. But with VS8, Qt 3.0.5 does not have integration, so I am obliged to invoke the MOC manually.

Aren't you bothered by the fact that Qt is silent when a connection fails?

Mokkan
Member #4,355
February 2004
avatar

I've never had problems with Qt's slots/signals, and I've always had to 'manually' invoke moc. I've found that it isn't difficult to add moc to makefiles, scons projects, or cmake projects.

Congrats on making your own though. Whatever works for you.

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

Aren't you bothered by the fact that Qt is silent when a connection fails?

Connections don't fail. they just might not be all that usefull if you're connecting to a signal thats not going to fire.

Also, if you dislike calling moc yourself, use qmake. it does all the moc, and uic goodness for you.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

axilmar
Member #1,204
April 2001

Quote:

Connections don't fail.

They do. If you mispell a signal or slot or a parameter inside a SIGNAL() or SLOT() expression, the only thing Qt will do is to output a warning message in the debug output. At least that's what version 3.0.5 does.

Quote:

Also, if you dislike calling moc yourself, use qmake. it does all the moc, and uic goodness for you.

I have no idea if qmake can be used instead of Microsoft's compiler inside the VS8 IDE.

Thomas Fjellstrom
Member #476
June 2000
avatar

Quote:

They do. If you mispell a signal or slot or a parameter inside a SIGNAL() or SLOT() expression, the only thing Qt will do is to output a warning message in the debug output. At least that's what version 3.0.5 does.

Right, it didn't fail at all. It connected a signal to a slot, just not the ones you wanted it too because you can't type ;)

Quote:

I have no idea if qmake can be used instead of Microsoft's compiler inside the VS8 IDE.

They have a VS plugin for Qt.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

axilmar
Member #1,204
April 2001

Quote:

Right, it didn't fail at all. It connected a signal to a slot, just not the ones you wanted it too because you can't type

Agreed. But that's human nature: sometimes you don't type what you should.

And then there is the problem of changing stuff: if you change a signal's signature and you forget to update the slots, the program will run normally.

My point is that the Qt signals & slots mechanism is more dangerous than using classes. With classes, the compiler makes sure the code works.

Quote:

They have a VS plugin for Qt.

In order to get integration with VS8 you have to buy a new Qt version.

Go to: