Qt提供的MessageBox只可以在gui线程(主线程)使用,于是需要QMessageBox进行封装,可以在非gui线程内被调用。
特性:
1.可以在任何线程调用;
2.show后和默认的MessageBox一样是阻塞的,MessageBox关闭后才会返回。
- 使用moveToThread将QMessageBox实际调用移动到主线程中,并使用QEventLoop实现阻塞。
声明
#include <QMessageBox> #include <QEventLoop> class ThreadInformationMessageBox : public QObject { Q_OBJECT private: const QString m_strTitle; const QString m_strMessage; public: ThreadInformationMessageBox(const QString &strTitle, const QString &strMessage); static void show(const QString &strTitle, const QString &strMessage); private: void readyShow(void); private slots: void onShow(void); };
实现
ThreadInformationMessageBox::ThreadInformationMessageBox(const QString &strTitle, const QString &strMessage) : m_strTitle(strTitle), m_strMessage(strMessage) { } void ThreadInformationMessageBox::show(const QString &strTitle, const QString &strMessage) { QEventLoop eventLoop; auto messageBox = new ThreadInformationMessageBox(strTitle, strMessage); connect(messageBox, SIGNAL(destroyed()), &eventLoop, SLOT(quit())); messageBox->readyShow(); eventLoop.exec(); } void ThreadInformationMessageBox::readyShow(void) { this->moveToThread(qApp->thread()); QTimer::singleShot(0, this, SLOT(onShow())); } void ThreadInformationMessageBox::onShow(void) { QMessageBox::information(NULL, m_strTitle, m_strMessage); this->deleteLater(); }
使用
ThreadInformationMessageBox::show("Title", "Message");
备注
该QMessageBox没有指定的父窗体,位置可能不是期望的,如果需要指定位置,则需要进行相应设置或移动。
- 使用线程内阻塞的信号槽连接方式实现QMessageBox。
代码
Q_SIGNALS: int SendMessageSignal(const QString& title, const QString& content, QMessageBox::Icon icon, const QString& button0Text, const QString& button1Text = QString(), const QString& button2Text = QString()); // 连接线程内的信号与匿名函数 connect(pObjectHasThread, &ObjectHasThread::SendMessageSignal, this, [=]( const QString& title, const QString& content, QMessageBox::Icon icon, const QString& button0Text, const QString& button1Text = QString(), const QString& button2Text = QString()) -> int { switch (icon) { case QMessageBox::Information: return QMessageBox::information(this, title, content, button0Text, button1Text, button2Text); break; case QMessageBox::Warning: return QMessageBox::warning(this, title, content, button0Text, button1Text, button2Text); break; case QMessageBox::Question: return QMessageBox::question(this, title, content, button0Text, button1Text, button2Text); break; case QMessageBox::Critical: return QMessageBox::critical(this, title, content, button0Text, button1Text, button2Text); break; default: return -1; } }, Qt::BlockingQueuedConnection);
备注
1. pObjectHasThread为自定义线程对象或含有线程操作的对象,需要在此线程操作中使用QMessageBox; 2. 使用时直接在pObjectHasThread对象中发射SendMessageSignal即可; 3. Qt::BlockingQueuedConnection连接方式实现了线程内阻塞,该种连接方式仅适用于信号和槽函数在不同线程中的情形; 4. int为匿名函数的返回值,即用户在QMessageBox弹出框中的选择。