从后台工作线程修改 Qt GUI [英] Modify Qt GUI from background worker thread
问题描述
我在 Qt 中工作,当我按下按钮 GO 时,我需要不断地将包发送到网络并使用我收到的信息修改界面.
I work in Qt and when I press the button GO I need to continuously send packages to the network and modify the interface with the information I receive.
问题是我在按钮中有一个 while(1)
所以按钮永远不会完成所以界面永远不会更新.我想在按钮中创建一个线程并将 while(){}
代码放在那里.
The problem is that I have a while(1)
in the button so the button never finishes so the interface is never updated. I thought to create a thread in the button and put the while(){}
code there.
我的问题是如何从线程修改界面?(例如,如何从线程修改文本框?
My question is how can I modify the interface from the thread? (For example how can I modify a textBox from the thread ?
推荐答案
关于 Qt 的重要一点是,您必须仅从 GUI 线程(即主线程)使用 Qt GUI.
Important thing about Qt is that you must work with Qt GUI only from GUI thread, that is main thread.
这就是为什么正确的做法是从worker通知主线程,而主线程中的代码实际上会更新文本框、进度条或其他东西.
That's why the proper way to do this is to notify main thread from worker, and the code in main thread will actually update text box, progress bar or something else.
我认为最好的方法是使用 QThread 而不是 posix 线程,并使用 Qt 信号 在线程之间进行通信.这将是你的工人,thread_func
的替代者:
The best way to do this, I think, is use QThread instead of posix thread, and use Qt signals for communicating between threads. This will be your worker, a replacer of 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 中的信号具有相同原型的槽:
In your widget, define a slot with same prototype as signal in .h:
class MyWidget : public QWidget {
// Your gui code
// Define slot:
public slots:
void onProgressChanged(QString info);
};
在.cpp中实现这个功能:
In .cpp implement this function:
void MyWidget::onProgressChanged(QString info) {
// Processing code
textBox->setText("Latest info: " + info);
}
现在在你想要生成线程的地方(点击按钮):
Now in that place where you want to spawn a thread (on button click):
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
在这里.
After you connect signal and slot, emiting slot with emit progressChanged(...)
in worker thread will send message to main thread and main thread will call the slot that is connected to that signal, onProgressChanged
here.
P.s.我还没有测试代码,所以如果我在某处错了,请随时提出修改建议
这篇关于从后台工作线程修改 Qt GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!