Badmanchild
Badmanchild

Reputation: 1020

Using Qt where worker thread creates new GUI elements

I will keep the code simple so that you guys can see what I'm trying to do ;) I am aware of all of the locking issues, etc. I'm trying to figure out how signals and slots play with threads.

In main.cpp:

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyConsole c;       // Subclasses QThread and implements run()
    MyReceiver r(app); // We pass app to MyReceiver for later (see below)
    QObject::connect(&c, SIGNAL(sendit()),
                     &r, SLOT(gotit()));
    c.start();         // Start the worker thread
    app.exec();
}

Assume that the signals and slots were properly set up in the header files (I've tested and they are). Now, here's the issue:

In MyReceiver.cpp:

void MyReceiver::gotit()
{
    QLabel *label = new QLabel(0, "Hello");  // Some GUI element, any will do
    app.setMainWidget(*label);               // Some GUI action, any will do
}

The question is: Because the MyReceiver object was created in main(), which is on the main thread, does that mean that the slots (e.g., gotit()) will run on the main thread and are therefore safe for doing GUI stuff? Even in cases where the signal was raised from a different QThread (like MyConsole in this example)?

Is there a better way to allow worker threads to interact with the GUI (for example, Obj-C/Cocoa have a "send message on main thread" type of approach). What is "The Qt way" of doing this?

Thanks in advance!

Upvotes: 5

Views: 1130

Answers (2)

awx
awx

Reputation: 126

By default (Qt::AutoConnection), slots will run in the thread the QObject was created in. So, no matter from what thread you emit the signal, the slot will be run always in the thread, the QObject "lives" in (if a Qt event loop is running in that thread, otherwise the event can't be delivered). Since the main thread will become the Qt GUI thread, this will work as expected. This is indeed the Qt way of interacting with the GUI. See also: http://doc.qt.nokia.com/4.7/thread-basics.html (look for thread affinity).

Upvotes: 5

Chris
Chris

Reputation: 17545

The "Qt way" to emit a signal from one thread and receive it in a different thread is to use a Queued connection

connect( obj, SIGNAL(foo()), other_obj, SLOT(bar()), Qt::QueuedConnection )

From the Qt documentation for Qt::QueuedConnection:

The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.

Upvotes: 2

Related Questions