Qt主界面假死解决
前言
在利用Qt进行可视化编程时,某个过于耗时的操作会造成界面卡死现象。例如用户点击界面的Button控件,程序会执行clicked槽函数中的操作,但是槽函数中的操作特别耗时,此时界面处于卡死状态(用户无法进行任何操作,包括拖动界面)。为了解决这一“假死”现象,需要用到多线程。
多线程解决Qt主界面假死的原理
当前我们编写的程序大多都是单线程执行,并且Qt的可视化界面逻辑代码也与执行耗时操作的代码处在同一个线程中。因此遇到耗时操作时,程序需要等到耗时操作执行完成后再继续执行后续代码,界面中的交互功能也不能使用,呈现出“假死”状态。而采用多线程编程,将耗时操作放在新开辟的线程中可以避免上述问题。下面将详细介绍如何解决Qt主界面假死问题
构造新的线程类workThread
Qt线程的创建有两种方式:
- 继承QThread的方式,然后重写run,但是这种方式官方已经不推荐了
- 继承QObject,构建新的类然后move到新的线程中
构建新的类中,重点需要关注信号(signals)和槽(slots)的定义与实现
- signals包括:任务开始(workStart)与任务结束(workFinished)
- slots包括:线程开始(start1)与操作执行(doWork)
- 在Widget.h文件中定义如下线程类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class workThread : public QObject
{
Q_OBJECT
public:
workThread(QObject* parent = nullptr);
~workThread();
bool m_bStart;
public slots:
void start1();
void doWork();
signals:
void workFinished();
void workStart();
}; - 在Widget.cpp文件中完善workThread类中的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22workThread::workThread(QObject* parent) : QObject(parent)
{
this->m_bStart = false;
}
workThread::~workThread()
{
}
void workThread::start1()
{
emit workStart(); //发送信号,表明线程开始工作
doWork(); //开始执行线程内的操作
}
void workThread::doWork()
{
for (int i = 0; i < 1000000; i++)
{
qDebug() << i;
}
emit workFinished(); //发送信号,表明线程结束工作
}
给Button绑定clicked事件测试
- 给Button绑定clicked事件
- 在clicked槽函数中创建一个新的线程m_workThread对象
- 创建定义好的workThread对象worker,move到新线程中
- 完成相应的信号与槽的连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15void QtWidgetsApplication1::on_pushButton_clicked()
{
QThread* m_workThread = new QThread();
workThread* worker = new workThread();
worker->moveToThread(m_workThread);
//建立信号槽连接
connect(m_workThread, &QThread::started, worker, &workThread::start1);
connect(worker, &workThread::workFinished, worker, &workThread::deleteLater);
connect(worker, &workThread::workFinished, m_workThread, &QThread::quit);
connect(m_workThread, &QThread::finished, m_workThread, &QThread::deleteLater);
worker->m_bStart = true;
m_workThread->start();
worker->m_bStart = false;
}
程序运行截图如下:
此时,程序在执行1000000次循环输出,而可视化界面不会卡死
注意:因为此时界面和耗时程序执行操作在两个线程,如果后续需要传递数据的话,可以将数据通过信号槽的方式传递
本文作者: 贾明晖
本文链接: http://minghuijia.cn/2022/03/13/Qt%E4%B8%BB%E7%95%8C%E9%9D%A2%E5%81%87%E6%AD%BB%E8%A7%A3%E5%86%B3/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!