前言:做项目时,遇到这样一个问题,在QtConcurrent线程中对QStandardItem*对象使用setText()函数,相应的ListView控件没有刷新,需要在界面点击一下控件,才能刷新。刚接手这个问题时给我的第一感觉是控件失焦。
QtConcurrent
因为第一感觉是失焦,所以在程序线程函数中对控件调用了setFocus(),结果程序直接报异常,问题大致是不能在其它线程对控件进行操作,也就是说创建控件的线程是主线程,而QtConcurrent新开了一个线程。因为对QtConcurrent第一次接触,索性在网上查了一下QtConcurrent的特性。
https://blog.csdn.net/Amnes1a/article/details/66470751
https://blog.csdn.net/fghler/article/details/109444779
主要参考了以上几篇文章,说的是QtConcurrent编写多线程程序的高级API,使用这个API可以使我们在不使用低级的线程元素…感觉就很高大上的样子。在使用上,相比于使用QThread的方法开线程,需要写一个类继承QThread的方式,QtConcurrent的方法简直是简单至极,甚至只要一行代码就行:QFuture future = QtConcurrent::run(func); 知道此事的我,对于之前苦逼的写着QThread子类的事情感到心力憔悴。不过,QtConcurrent也存在不足,据大佬说无法使用signal/slot的槽函数。因此,QtConcurrent的应用场景应该是不需要额外交互,计算耗时,只需要关注计算结果的场合。当然,QFutureWatcher也提供了多种signal/slot的槽函数,但对于把QtConcurrent写成轮询线程,需要处理多种数据的方式可能不适用。因此需要另外一种方式与主线程进行交互。好了,不说废话了。上代码。
postEvent
在QtConcurrent线程函数中调用postEvent,注意QEvent* e一定要用new,因为QT会自动delete这个指针,所以不用new的话,会报异常。
QEvent *e = new QEvent(QEvent::User);
QCoreApplication::postEvent(this, e);
event(QEvent * e)
在主线程中添加这个函数,应该是重写。
protected:
bool event(QEvent * e);
bool demo::event(QEvent * e)
{
if (e->type() == QEvent::User) {
//更新控件
ui.pushButton->setText(QString::number(m_num));
}
return QWidget::event(e);
}