在Qt应用程序开发中,我们经常会遇到这样的问题:当执行一个耗时操作时,整个界面会卡住,无法响应任何用户操作,甚至连一个简单的提示弹窗都无法正常显示。本文将介绍两种解决这个问题的方法,并通过完整的代码示例进行说明。
问题描述
先来看一个常见的错误示例:
#include <QMainWindow>
#include <QPushButton>
#include <QMessageBox>
#include <QVBoxLayout>
#include <QThread>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
{
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
QPushButton *button = new QPushButton("生成条码", this);
layout->addWidget(button);
connect(button, &QPushButton::clicked, this, &MainWindow::onGenerateBarcodeClicked);
}
private slots:
void onGenerateBarcodeClicked()
{
// 显示提示对话框
QMessageBox::information(this, "提示", "条码生成中,请等待...");
// 模拟耗时的条码生成操作
QThread::sleep(5); // 暂停5秒
// 显示完成对话框
QMessageBox::information(this, "提示", "生成成功");
}
};
这个代码看起来很合理:点击按钮后,先显示一个"条码生成中"的提示框,然后执行条码生成操作,最后显示"生成成功"的提示。但实际运行时会发现,第一个提示框根本不会显示,直到5秒后条码生成完成,才会直接显示"生成成功"的提示框。
这是因为Qt的UI是单线程的,所有UI更新都必须在主线程中进行。当执行QThread::sleep(5)
时,整个主线程被阻塞,无法处理UI事件,包括绘制和显示对话框。因此,第一个提示框虽然被创建了,但无法在屏幕上显示出来。
方法一:使用QCoreApplication::processEvents()
第一种解决方法是在耗时操作中定期调用QCoreApplication::processEvents()
,让Qt有机会处理UI事件。
#include <QMainWindow>
#include <QPushButton>
#include <QMessageBox>
#include <QVBoxLayout>
#include <QThread>
#include <QProgressDialog>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
{
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
QVBoxLayout *layout = new