之前用WPF开发,处理逻辑就是1,处理前显示等待窗口,2、同步处理改未异步,3、处理完毕后关闭等待窗口。
Qt应该也是类似的处理逻辑:
一、创建等待处理窗口(采用了QMoive 载入gif动画方式,更新方便)
头文件:
#ifndef QWAITINGDIALOG_H
#define QWAITINGDIALOG_H
#include <QWidget>
#include <QMovie>
#include <QLabel>
class QWaitingDialog : public QWidget
{
Q_OBJECT
public:
explicit QWaitingDialog(QWidget *parent = nullptr);
~QWaitingDialog();
private:
QMovie *m_movie=nullptr;
QLabel *m_lable=nullptr;
};
#endif // QWAITINGDIALOG_H
源文件:
#include "qwaitingdialog.h"
QWaitingDialog::QWaitingDialog(QWidget *parent) : QWidget(parent)
{
m_lable=new QLabel(this);
m_lable->setFixedSize(250,250);
this->setWindowOpacity(0.8);
setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);//设置为对话框风格,并且去掉边框
this->setWindowModality(Qt::WindowModal);
m_movie=new QMovie(":/image/img/wait.gif");
m_lable->setStyleSheet("background-color:transparent;");
m_lable->setMovie(m_movie);
m_lable->setScaledContents(true);
m_movie->start();
}
QWaitingDialog::~QWaitingDialog()
{
delete m_lable;
delete m_movie;
}
二、使用方法:
int WaveSyllable::actionFuncAutoDetectSyllables()
{
int ret=0;
QWaitingDialog *p_wait=new QWaitingDialog(this);
p_wait->show();
QFuture<int> fut_syllable=QtConcurrent::run([=]()->int{ return
syllables_into_db_and_display();});//异步处理
ret=fut_syllable.result();
p_wait->close();
if(waitingDialog!=nullptr)
delete waitingDialog;
return ret;
}
怀着激动心情运行,卧槽,主界面仍然卡死,问题出在哪里呢。网上找了一天资料,基本都是等待窗口的设计,具体调用卡死问题都没找到,有提到使用 QApplication::processEvents(); 来通知主界面运行的。开始我放到QWaitingDialog中,写了个定时器,循环调用通知,运行还是无法解决。最终找到了解决方案,在异步处理未完成时循环调用,代码如下:
int WaveSyllable::actionFuncAutoDetectSyllables()
{
int ret=0;
QWaitingDialog *p_wait=new QWaitingDialog(this);
p_wait->show();
QFuture<int> fut_syllable=QtConcurrent::run([=]()->int{ return
syllables_into_db_and_display();}); //异步处理
while(!fut_syllable.isFinished())
{
QApplication::processEvents(QEventLoop::AllEvents, 100);//唤醒主界面
}
ret=fut_syllable.result();
p_wait->close();
if(waitingDialog!=nullptr)
delete waitingDialog;
return ret;
}
再次运行,已经正常解决了卡死问题。