QT动态启动界面,不会卡死

一般需要启动界面的程序会把加载工作放到子线程,在主线程播放启动界面,但是有时候又确实需要在主界面耗时加载一些东西,就没办法播放动态启动界面了,而QT又不支持子线程刷新UI。
所以写了一个多进程启动界面组件。
QT动态启动界面,不会卡死_第1张图片
main.cpp

#include 
#include 
#include "YSplashScreen.h"
#include 
#include 
#include 

int main(int argc, char* argv[])
{
    QApplication application(argc, argv);

    QWidget w;
    YSplashScreenApplication ssa(w);

    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    w.show();
    ssa.stop();

    return application.exec();
}

YSplashScreen.h

#ifndef YSPLASHSCREEN_H
#define YSPLASHSCREEN_H

#include 

#define YSplashScreenApplicationSimple(widOrWidget) \
    YSplashScreenApplication __simpleYSplashScreenApplication(widOrWidget);\
    Q_UNUSED(__simpleYSplashScreenApplication);
class QProcess;
class YSplashScreenApplication{
public:
    ~YSplashScreenApplication();
    YSplashScreenApplication() = default;
    explicit YSplashScreenApplication(WId wid);//默认设置
    inline YSplashScreenApplication(QWidget* widget): YSplashScreenApplication(widget->winId()){}
    inline YSplashScreenApplication(QWidget& widget): YSplashScreenApplication(widget.winId()){}
    void check();//检查是否是启动界面进程
    void start(WId wid);//打开启动界面
    inline void start(QWidget* widget) { start(widget->winId()); }
    inline void start(QWidget& widget) { start(widget.winId()); }
    void stop();//关闭启动界面
    inline void setSplashScreenWidget(QWidget* widget) { splashScreenWidget = widget; }//自定义设置动态启动界面
private:
    WId wid;
    void exec(WId wid);
    QProcess* process = nullptr;
    QWidget* splashScreenWidget = nullptr;
    bool isChecked = false;
};

class YSplashScreen : public QWidget
{
public:
    explicit YSplashScreen(QWidget *parent = nullptr);

public:
    void paintEvent(QPaintEvent *) override;
    void timerEvent(QTimerEvent*) override;
    int currentIndex = 0;
};

#endif // YSPLASHSCREEN_H

YSplashScreen.cpp

#include "YSplashScreen.h"
#include 
#include 
#include 
#include 
#include 

YSplashScreenApplication::~YSplashScreenApplication()
{
    if(process){
        stop();
    }
}

YSplashScreenApplication::YSplashScreenApplication(WId wid)
{
    check();
    start(wid);
}

void YSplashScreenApplication::check()
{
    const QStringList& arguments = qApp->arguments();
    if(arguments.size() == 3 && arguments.last() == "YSplashScreen"){
        WId wid = arguments.at(1).toULongLong();
        exec(wid);
    }
    isChecked = true;
}

void YSplashScreenApplication::start(WId wid)
{
    if(!isChecked){
        check();
    }
    process = new QProcess;
    process->start(qApp->applicationFilePath(), QStringList{QString::number(wid), "YSplashScreen"});
}

void YSplashScreenApplication::stop()
{
    if(process){
        process->close();
        process->deleteLater();
        process = nullptr;
    }
}

void YSplashScreenApplication::exec(WId wid)
{
    this->wid = wid;
    QTimer* timer = new QTimer;
    QObject::connect(timer, &QTimer::timeout, [this]{
        QScreen* screen = qApp->primaryScreen();
        QPixmap pixmap = screen->grabWindow(this->wid, 0, 0, 1, 1);
        if(pixmap.isNull()){
            qApp->quit();
        }
    });
    timer->start(300);
    if(!splashScreenWidget){
        setSplashScreenWidget(new YSplashScreen);
    }

    splashScreenWidget->setWindowFlag(Qt::ToolTip);
    splashScreenWidget->setWindowFlag(Qt::FramelessWindowHint);
    splashScreenWidget->setAttribute(Qt::WA_TranslucentBackground, true);
    splashScreenWidget->setAutoFillBackground(false);
    splashScreenWidget->show();
    exit(qApp->exec());
}

YSplashScreen::YSplashScreen(QWidget *parent) : QWidget(parent)
{
    setAutoFillBackground(false);
    setWindowFlag(Qt::ToolTip);
    setWindowFlag(Qt::FramelessWindowHint);
    setFocusPolicy(Qt::StrongFocus);
    setAttribute(Qt::WA_TranslucentBackground, true);

    QSize desktopSize = qApp->primaryScreen()->size();
    setGeometry((desktopSize.width() - 200) / 2, (desktopSize.height() - 200) / 2, 200, 200);

    startTimer(100);
}

void YSplashScreen::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing);
    painter.setPen(Qt::NoPen);
    QLinearGradient gradient(width() / 2, 0, width() / 2, height());
    gradient.setColorAt(0, QColor(1,209,255));
    gradient.setColorAt(1, QColor(0,135,191));
    painter.setBrush(gradient);

    painter.drawRoundedRect(rect(), 10, 10);

    painter.setPen(Qt::white);
    painter.setFont(QFont("楷体", 20, 100));
    painter.drawText(QRect(0, 0, 200, 80), Qt::AlignCenter, "正在启动...");
    painter.setPen(Qt::NoPen);

    painter.translate(100, 130);
    painter.setBrush(Qt::white);
    painter.rotate(36 * currentIndex);
    for(int i = 0; i < 10; ++i){
        painter.rotate(-36);
        painter.drawEllipse(QRect(33 + i, i - 12, 24 - 2 * i, 24 - 2 * i));
    }
}

void YSplashScreen::timerEvent(QTimerEvent *)
{
    currentIndex = (currentIndex + 1) % 10;
    update();
}

你可能感兴趣的:(QT,qt,ui)