Qt启动页多线程
项目需要在Qt进入启动页之前加载一个大模型文件,同时要有一个页面用来提示用户加载状态。
这里就需要用到多线程了,如果在单线程操作,要么需要等到文件加载完毕后才能显示等待页,要么干脆跳过了模型文件的加载,都是不符合需求的。
我们通过代码分析。
首先要绘制加载页,这里做一个非常简单的等待页,只有一行Loading…,可根据需求修改。
waiting.h
#ifndef WAITING_H
#define WAITING_H
#include <QDialog>
#include <QLabel>
#include <QMovie>
class Waiting : public QDialog
{
Q_OBJECT
public:
explicit Waiting(QDialog *parent = 0);
private:
QLabel *label;
};
#endif // WAITING_H
waiting.cpp
#include <waiting.h>
Waiting::Waiting(QDialog *parent):
QDialog(parent)
{
this -> setWindowFlags ( Qt ::FramelessWindowHint );
//this->setWindowOpacity(1);
setFixedSize(320,180);
//提示Label
label = new QLabel(this);
label -> setGeometry(0,0,320,180);
label -> setText("Loading...");
label -> setScaledContents(true);
label -> setAlignment(Qt::AlignCenter);
label -> setStyleSheet("font-size:24pt;color:#1644B0");
}
然后就需要写多线程了,这里需要注意,一定要把费事费力的操作放在子线程里,否则会造成主线程阻塞卡死!!
waitingthread.h
#ifndef WAITINGTHREAD_H
#define WAITINGTHREAD_H
#include <QThread>
#include <QDebug>
#include "大文件api"
extern 大文件api;
class waitingThread : public QThread
{
Q_OBJECT
public:
explicit waitingThread(QObject *parent = nullptr);
void run(); //任务处理线程
bool isStop;//线程工作标志
};
#endif // WAITINGTHREAD_H
waitingthread.cpp
#include "waitingthread.h"
#include "waiting.h"
waitingThread::waitingThread(QObject *parent)
{
isStop = false;
}
void waitingThread::run() //子线程核心操作放在这里
{
大文件api.init(); // initialize API
isStop = true;
}
然后就是在主程序里操作了。这里需要注意的点也很多,先放代码。
#include <QApplication>
#include <QThread>
#include <跳转页.h>
#include <waitingthread.h>
#include <waiting.h>
#include "大文件api"
大文件api声明;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
waitingThread *wt = new waitingThread;
wt -> start();
Waiting *w = new Waiting();
w -> show();
while(true){
if(wt -> isStop == true)
{
w -> close();
//从屏保页开始
new跳转页;
跳转页 -> show();
break;
}else{
QEventLoop eventloop;
QTimer::singleShot(1000, &eventloop, SLOT(quit())); //wait 1s
eventloop.exec();
}
}
return a.exec();
}
首先要先执行子线程,后台开始处理加载大文件操作。然后显示等待页面,直到大文件加载完,加载标记isStop变为true的时候,再进入跳转页。顺序很重要。
因为要连续地判断加载标记当前的状态,因此这里需要用到死循环。但是单纯的死循环必定会造成主程序阻塞卡死,导致等待页也显示不出来,因此需要在死循环中加入阻塞,防止卡死。
阻塞如果使用sleep(),理论上也可以,但这里会导致我的Label刷新不出来,等待页还是不能正确显示。所以这里用了QEventLoop和QTimer的singleShot,死循环到这里每次阻塞1秒的时间,这样等待页面waiting就可以正确加载出来了。