当 GUI 冻结时显示带有 QThread 的 QMessageBox
Posted
技术标签:
【中文标题】当 GUI 冻结时显示带有 QThread 的 QMessageBox【英文标题】:showing QMessageBox with QThread when GUI frozen 【发布时间】:2013-11-20 23:19:49 【问题描述】:当我进行一些绘图工作时,Qt GUI 冻结。此时我想显示“正在加载..”消息框。我为此使用 QThread,但我做不到。
我的 QThread 类
myThread.cpp
#include "myThread.h"
#include <QtCore>
myThread::myThread(QObject *parent) :
QThread(parent)
void myThread::run()
emit threadSignal();
myThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
class myThread : public QThread
Q_OBJECT
public:
explicit myThread(QObject *parent = 0);
void run();
signals:
void threadSignal();
public slots:
;
我写在我的主头文件中
public:
myThread *mess;
QMessageBox box;
public slots:
void threadSlot();
我在我的主 cpp 文件中写道:
Archive::Archive(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Archive)
ui->setupUi(this);
mess=new myThread(this);
connect(mess, SIGNAL(threadSignal()), this, SLOT(threadSlot()));
box.setWindowFlags(Qt::WindowStaysOnTopHint);
void Archive::threadSlot()
box.show();
在我的主 cpp 文件中有一个冻结 GUI 的功能。
void Archive::plot()
mess->start();
//heavy work. It takes 2-3 second and GUI become unresponsive.
我希望该线程首先启动并显示 QmessageBox。 plot() 函数结束后,QmessageBox 消失了。但是使用此代码 QmessageBox 在 plot() 函数结束后显示。为什么会这样?
我使用 Qt 4.8.5
谢谢。
【问题讨论】:
如果所有繁重的工作都在主线程上完成,你的myThread
对象的目的是什么?
我只想显示一个带有文本“Wait”的 QMessageBox。如果我在主线程中执行此操作 QmessageBox 在 GUI 冻结之前不会出现。
那么你应该把繁重的工作转移到你的myThread
对象上,并将GUI的东西放在你的主线程中,而不是相反。
【参考方案1】:
Qt 中的 GUI 类只能从主线程访问。
这个问题的官方解决方案是在不同的线程中完成繁重的工作,而不是让你的 GUI 冻结。请参阅https://doc.qt.io/qt-5/threads-technologies.html 了解在 Qt 中使用线程的不同方式。
警告:您应该不向派生自 QThread 的类添加槽。来自文档(https://doc.qt.io/qt-5/qthread.html):
重要的是要记住 QThread 实例存在于旧的 实例化它的线程,而不是在调用 run() 的新线程中。 这意味着 QThread 的所有排队槽都将在旧的 线。因此,希望在新线程中调用槽的开发人员 必须使用工作对象方法;新插槽不应该 直接在子类 QThread 中实现。
这些链接适用于 Qt 5,但大多数概念也适用于 Qt 4.8。
【讨论】:
以上是关于当 GUI 冻结时显示带有 QThread 的 QMessageBox的主要内容,如果未能解决你的问题,请参考以下文章