QT + How to call slot from custom C++ code running in a different thread

江枫思渺然 提交于 2019-11-29 09:21:54
Caleb Huitt - cjhuitt

In addition to stribika's answer, I often find it easier to use a signal/slot connection. You can specify that it should be a queued connection when you connect it, to avoid problems with the thread's signals being in the context of its owning object.

class mythread : public QThread
{
signals:
    void appendText( QString );
public:

    mythread(mywindow* win){this->w = win;};
    mywindow* w;
    void run()
    {
        emit ( appendText( "Hello" ) );
    };
};

int main(int argc, char *argv[])
{
    QApplication* a = new QApplication(argc, argv);
    mywindow* w = new mywindow();

    w->show();
    mythread* thr = new mythread(w);
    (void)connect( thr, SIGNAL( appendText( QString ) ),
                   w->ui.textEdit, SLOT( append( QString ) ),
                   Qt::QueuedConnection ); // <-- This option is important!
    thr->start();

    return a->exec();
}

stribika got it almost right:

QMetaObject::invokeMethod( textEdit, "append", Qt::QueuedConnection,
                           Q_ARG( QString, myString ) );

cjhuitt's right, though: You usually want to declare a signal on the thread and connect it to the append() slot, to get object lifetime management for free (well, for the price of a minor interface change). On a sidenote, the additional argument:

               Qt::QueuedConnection ); // <-- This option is important!

from cjhuitt's answer isn't necessary anymore (it was, in Qt <= 4.1), since connect() defaults to Qt::AutoConnection which now (Qt >= 4.2) does the right thing and switches between queued and direct connection mode based on QThread::currentThread() and the thread affinity of the receiver QObject at emit time (instead of sender and receiver affinity at connect time).

You need to use QMetaObject::invokeMethod. For example:

void MyThread::run() {
    QMetaObject::invokeMethod(label, SLOT(setText(const QString &)), Q_ARG(QString, "Hello"));
}

(The above code comes from here: http://www.qtforum.org/article/26801/qt4-threads-and-widgets.html)

I don't think you are allowed to call directly things that results in paint events from any other threads than the main thread. That will result in a crash.

I think you can use the event loop to call things asynchronously so that the main gui thread picks up and then does the updating from the main thread, which is what cjhuitt suggests.

What if our thread affinity says GUI, but we're not in the GUI thread, nor in a QThread?

What I mean is, a non-Qt (notification) thread calls a QObject's interface method, in which we emit an AutoConnected signal. The Thread affinity of the QObject is Main thread, but the procedure is actually called from another thread. What'll the Qt do here?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!