从后台工作线程修改Qt GUI

我在Qt中工作,当我按下GObutton时,我需要不断地将包发送到networking,并使用我收到的信息修改接口。

问题是,我有一段while(1)在button,所以button永远不会完成,所以接口永远不会更新。 我想在button中创build一个线程,并把while(){}代码放在那里。

我的问题是我怎样才能从线程修改接口? (例如,我怎样才能从线程修改文本框?

Solutions Collecting From Web of "从后台工作线程修改Qt GUI"

关于Qt的一个重要的事情是,你只能从GUI线程(这是主线程)使用Qt GUI。

这就是为什么正确的方法是从工作人员通知主线程,而主线程中的代码实际上会更新文本框,进度条或其他内容。

我认为最好的方法是使用QThread而不是posix线程,并使用Qt 信号来进行线程之间的通信。 这将是你的工作者, thread_func的替代者:

 class WorkerThread : public QThread { void run() { while(1) { // ... hard work // Now want to notify main thread: emit progressChanged("Some info"); } } // Define signal: signals: void progressChanged(QString info); }; 

在你的小部件中,用.h中的信号定义一个与原型相同的插槽

 class MyWidget : public QWidget { // Your gui code // Define slot: public slots: void onProgressChanged(QString info); }; 

在.cpp中实现这个功能:

 void MyWidget::onProgressChanged(QString info) { // Processing code textBox->setText("Latest info: " + info); } 

现在在那个你想要产生一个线程的地方(点击按钮):

 void MyWidget::startWorkInAThread() { // Create an instance of your woker WorkerThread *workerThread = new WorkerThread; // Connect our signal and slot connect(workerThread, SIGNAL(progressChanged(QString)), SLOT(onProgressChanged(QString))); // Setup callback for cleanup when it finishes connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); // Run, Forest, run! workerThread->start(); // This invokes WorkerThread::run in a new thread } 

连接信号和插槽后,在工作线程中emit progressChanged(...)插槽将发送消息到主线程,主线程将调用连接到该信号的插槽, onProgressChanged在这里。

Ps我还没有测试代码,所以随时提出一个编辑,如果我错了某个地方

你可以使用invokeMethod()或者Signals和Slot机制。基本上有很多例子,比如如何发送信号以及如何在SLOT中接收。但是,InvokeMethod看起来很有趣。

下面是示例,它显示了如何从线程更改标签的文本:

//file1.cpp

 QObject *obj = NULL; //global QLabel *label = new QLabel("test"); obj = label; //Keep this as global and assign this once in constructor. 

接下来在你的WorkerThread中,你可以这样做:

//file2.cpp(即线程)

 extern QObject *obj; void workerThread::run() { for(int i = 0; i<10 ;i++ { QMetaObject::invokeMethod(obj, "setText", Q_ARG(QString,QString::number(i))); } emit finished(); } 

你开始线程传递一些指向线程函数的指针(在posix中线程函数有签名void *(thread_func)(void *) ,在windows下也是相同的) – 而且你完全可以自由的将指针发送给你自己的数据(struct或者什么的),并从线程函数中使用它(将指针指向正确的类型)。 那么,内存管理应该尽管出来(所以你既不泄漏内存也不使用已经释放的线程内存),但这是一个不同的问题