从后台工作线程修改 Qt GUI
- 2024-10-21 09:14:00
- admin 原创
- 88
问题描述:
我在 Qt 中工作,当我按下按钮 GO 时,我需要不断地向网络发送包并使用收到的信息修改界面。
问题是我while(1)
在按钮中有一个,所以按钮永远不会完成,所以界面永远不会更新。我想在按钮中创建一个线程并将代码放在while(){}
那里。
我的问题是如何从线程修改界面?(例如,如何从线程修改文本框?
解决方案 1:
关于 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
。
我还没有测试过代码,所以如果我哪里错了,请随时提出修改建议
解决方案 2:
因此,该机制是您无法从线程内部修改小部件,否则应用程序将崩溃并出现以下错误:
QObject::connect: Cannot queue arguments of type 'QTextBlock'
(Make sure 'QTextBlock' is registered using qRegisterMetaType().)
QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)
Segmentation fault
为了解决这个问题,您需要将线程工作封装在一个类中,例如:
class RunThread:public QThread{
Q_OBJECT
public:
void run();
signals:
void resultReady(QString Input);
};
其中 run() 包含您想要做的所有工作。
在您的父类中,您将有一个生成数据的调用函数和一个 QT 小部件更新函数:
class DevTab:public QWidget{
public:
void ThreadedRunCommand();
void DisplayData(QString Input);
...
}
然后调用线程,你将连接一些插槽,这
void DevTab::ThreadedRunCommand(){
RunThread *workerThread = new RunThread();
connect(workerThread, &RunThread::resultReady, this, &DevTab::UpdateScreen);
connect(workerThread, &RunThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
连接函数有4个参数,参数1为原因类,参数2为该类中的信号。参数3为回调函数的类,参数4为该类中的回调函数。
然后你将在子线程中有一个函数来生成数据:
void RunThread::run(){
QString Output="Hello world";
while(1){
emit resultReady(Output);
sleep(5);
}
}
然后,您将在父函数中有一个回调来更新小部件:
void DevTab::UpdateScreen(QString Input){
DevTab::OutputLogs->append(Input);
}
然后,当您运行它时,父级中的小部件将在线程中每次调用 emit 宏时更新。如果连接函数配置正确,它将自动获取发出的参数,并将其存储到回调函数的输入参数中。
工作原理:
我们初始化课程
我们设置了插槽来处理线程完成时发生的事件以及如何处理“返回”的
emit
数据,因为我们无法以通常的方式从线程返回数据然后我们通过调用来运行该线程(该调用被硬编码到 QThread 中),QT在类中
->start()
查找硬编码名称memberfunction.run()
每次
emit
在子线程中调用 resultReady 宏时,它都会将 QString 数据存放到线程间某个共享数据区域中QT 检测到 resultReady 已触发,并向您的函数 UpdateScreen(QString) 发出信号,以接受从 run() 发出的 QString 作为父线程中的实际函数参数。
每次触发 emit 关键字时都会重复此操作。
本质上,这些connect()
函数是子线程和父线程之间的接口,以便数据可以来回传输。
注意: resultReady() 不需要定义。可以将其视为 QT 内部存在的宏。
解决方案 3:
您可以使用invokeMethod()或信号和槽机制,基本上有很多例子,比如如何发出信号以及如何在槽中接收信号。但是,InvokeMethod看起来很有趣。
下面是一个示例,展示了如何从线程更改标签的文本:
//文件1.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();
}
解决方案 4:
你启动线程并将一些指针传递给线程函数(在 posix 中,线程函数具有签名void (thread_func)(void),在 windows 下也是如此) - 并且你完全可以自由地将指针发送到你自己的数据(结构或其他东西)并从线程函数中使用它(将指针转换为适当的类型)。好吧,内存管理应该是经过深思熟虑的(这样你就不会泄漏内存也不会使用线程中已经释放的内存),但这是一个不同的问题
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件