在非gui線程使用QMessageBox

Qt提供的MessageBox只可以在gui線程(主線程)使用,於是需要QMessageBox進行封裝,可以在非gui線程內被調用。
特性:
1.可以在任何線程調用;
2.show後和默認的MessageBox一樣是阻塞的,MessageBox關閉後纔會返回。

  1. 使用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沒有指定的父窗體,位置可能不是期望的,如果需要指定位置,則需要進行相應設置或移動。
  1. 使用線程內阻塞的信號槽連接方式實現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彈出框中的選擇。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章