With a queued connection, for each slot connected to a signal there is a QMetaCallEvent
posted to the connected slot object's event queue. The events are delivered when the event loop runs. The code below outputs:
about to emit
done emitting
in aSlot()
class MyObject {
Q_OBJECT
Q_SIGNAL void aSignal();
Q_SLOT void aSlot() { qDebug() << "in aSlot()"; }
public:
MyObject(Qt::ConnectionType conn = Qt::AutoConnection) {
// QObject::connect() defaults the connection type to Qt::AutoConnection,
// we merely duplicate this behavior.
connect(this, SIGNAL(aSignal()), SLOT(aSlot()), conn);
qDebug() << "about to emit";
emit aSignal();
qDebug() << "done emitting";
}
};
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
MyObject obj(Qt::QueuedConnection);
QCoreApplication::processEvents();
return 0;
}
The problem can now be reformulated to: How to force removal of duplicate QMetaCallEvent
events from the event queue? This is known as event compression. I have already provided a canonical answer to that question. For user input, you want the most recently emitted signal to be retained, not the oldest one, but I've implemented both behaviors in the answer code.
Using the code from my answer, your example merely needs the following in the main()
function:
int main(int argc, char ** argv) {
CompressorApplication<QApplication> app(argc, argv);
app.addCompressedSignal(MyObjType2::staticMetaObject.method(MyObjType2::staticMetaObject.indexOfSignal("obj2Signal(int)")));
MainWindow w;
w.show();
return app.exec();
}
Note: If one were connecting objects with the default Qt::AutoConnection
and the objects were in the same thread, then the concept of a queue wouldn't apply at all. The slot is called before the signal function returns and nothing needs to be queued! The code below will output:
about to emit
in aSlot()
done emitting
// MyObject as above
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
MyObject obj;
return 0;
}