我是QT的新手,我正在做一些学习。
我想触发一个从C ++线程(目前是Qthread)修改GUI小部件的插槽。
不幸的是我得到了:ASSERTION失败了:Q_ASSERT(qApp&& qApp-> thread()== QThread :: currentThread());
这里有一些代码:
(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();
}
窗口:
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);
};
所以我很好奇如何用不同的线程中的代码更新gui部分。
感谢您的帮助
答案 0 :(得分:16)
QMetaObject::invokeMethod( textEdit, "append", Qt::QueuedConnection,
Q_ARG( QString, myString ) );
但是,cjhuitt是对的:您通常希望在线程上声明一个信号并将其连接到append()
插槽,以免费获得对象生命周期管理(好的,以次要接口更改的价格)。在旁注中,附加论点:
Qt::QueuedConnection ); // <-- This option is important!
来自cjhuitt的答案不再是必要的(在Qt&lt; = 4.1中),因为connect()
默认为Qt::AutoConnection
现在(Qt> = 4.2)做正确的事情,基于QThread::currentThread()
在排队和直接连接模式之间切换,并在发出时间时接收器QObject
的线程亲和力(在连接时不是发送者和接收者亲和力)。
答案 1 :(得分:8)
除了stribika's answer之外,我经常发现使用信号/插槽连接更容易。您可以在连接时指定它应该是排队连接,以避免线程信号出现在其拥有对象的上下文中。
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();
}
答案 2 :(得分:6)
您需要使用QMetaObject::invokeMethod。例如:
void MyThread::run() {
QMetaObject::invokeMethod(label, SLOT(setText(const QString &)), Q_ARG(QString, "Hello"));
}
(上面的代码来自:http://www.qtforum.org/article/26801/qt4-threads-and-widgets.html)
答案 3 :(得分:2)
我不认为你可以直接调用任何导致任何油漆事件的事情 其他线程比主线程。这将导致崩溃。
我认为你可以使用事件循环异步调用事物,以便主gui线程获取,然后从主线程进行更新,这是cjhuitt建议的。
答案 4 :(得分:2)
如果我们的线程亲和力说GUI,但我们不在GUI线程中,也不在QThread中,该怎么办?
我的意思是,非Qt(通知)线程调用QObject的接口方法,在该方法中我们发出自动连接信号。 QObject的Thread亲缘关系是主线程,但实际上是从另一个线程调用该过程。 Qt在这做什么?