I am new to QT and I am doing some learning.
I would like to trigger a slot that modify a GUI widget from a C++ thread(Currently a Qthread).
Unfortunatly I get a: ASSERTION failed at: Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
here is some code:
(MAIN + Thread class)
class mythread : public QThread
{
public:
mythread(mywindow* win){this->w = win;};
mywindow* w;
void run()
{
w->ui.textEdit->append("Hello"); //<--ASSERT FAIL
//I have also try to call a slots within mywindow which also fail.
};
};
int main(int argc, char *argv[])
{
QApplication* a = new QApplication(argc, argv);
mywindow* w = new mywindow();
w->show();
mythread* thr = new mythread(w);
thr->start();
return a->exec();
}
Window:
class mywindow : public QMainWindow
{
Q_OBJECT
public:
mywindow (QWidget *parent = 0, Qt::WFlags flags = 0);
~mywindow ();
Ui::mywindow ui;
private:
public slots:
void newLog(QString &log);
};
So I am curious on how to update the gui part by code in a different thread.
Thanks for helping
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 it's owning object.
stribika got it almost right:
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:from cjhuitt's answer isn't necessary anymore (it was, in Qt <= 4.1), since
connect()
defaults toQt::AutoConnection
which now (Qt >= 4.2) does the right thing and switches between queued and direct connection mode based onQThread::currentThread()
and the thread affinity of the receiverQObject
at emit time (instead of sender and receiver affinity at connect time).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.
You need to use QMetaObject::invokeMethod. For example:
(The above code comes from here: http://www.qtforum.org/article/26801/qt4-threads-and-widgets.html)
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?