Qt5多线程/线程池技术集锦(2)如何在子线程更新ui窗口

上一篇介绍了基础知识

Qt5多线程/线程池技术集锦(1)基础知识篇_libaineu2004的博客-CSDN博客_qt5 线程池

Qt下多线程的几种使用方法, 以及注意事项

第一种方法: 
1. 创建一个类从QThread类派生 
2. 在子线程类中重写 run 函数, 将处理操作写入该函数中 
3. 在主线程中创建子线程对象, 启动子线程, 调用start()函数 


第二种方法: 
1. 将业务处理抽象成一个业务类, 在该类中创建一个业务处理函数 
2. 在主线程中创建一QThread类对象 
3. 在主线程中创建一个业务类对象 
4. 将业务类对象移动到子线程中 
5. 在主线程中启动子线程 
6. 通过信号槽的方式, 执行业务类中的业务处理函数


第三种方法:
QFuture<void> f1 = QtConCurrent::run(processFun, command)


多线程使用注意事项: 
1. 业务对象, 构造的时候不能指定父对象 
2. 子线程中不能处理ui窗口(ui相关的类) 
3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口

这篇讲讲多线程里怎么更新窗口ui

第一种方法:

子线程发信号给主线程,更新UI。通过信号槽的机制可以实现,子线程发信号给主线程即可。不会阻塞。

启动线程
m_future_2d_SectionChart = QtConcurrent::run(this, &FormContent::thread_draw2D_SectionChart);
 
子线程
void FormContent::thread_draw2D_SectionChart(void)//绘制2D截面图
{
	qDebug() << "sub thread id:" << QThread::currentThreadId();
	connect(this, SIGNAL(sig_updateUI_SectionChart()), this, SLOT(slot_updateUI_SectionChart()));
 
while (true)
{
//去主线程更新UI
		emit sig_updateUI_SectionChart();
}
 
}
 
主线程
void FormContent::slot_updateUI_SectionChart(void)//更新2D截面图
{
   qDebug() << "main thread id:" << QThread::currentThreadId();
	m_pFormTimeline->updateSectionChart();
}

第二种方法:(推荐)

我们可以在线程函数里使用QMetaObject::invokeMethod来实现异步更新ui

举例如下:

1.主界面里面有个控件QTextBrowser

2.子线程在执行数据计算,最终想把计算结果输出到控件QTextBrowser

3.Qt子线程不能操作UI,必须发送到主线程。那么在线程执行函数里,这样写:

QMetaObject::invokeMethod(qApp, [this, equivalentX, equivalentY] {
    ui->textBrowser_ret->append(tr("equivalent估值,x:%1mm").arg(equivalentX));
    ui->textBrowser_ret->append(tr("equivalent估值,y:%1mm").arg(equivalentY));
});

关于QMetaObject::invokeMethod的原理,可以参见6.5大侠的教程

https://gitee.com/feiyangqingyun/qtkaifajingyan

猜你喜欢

转载自blog.csdn.net/libaineu2004/article/details/126176523