Qt将所有GUI相关的处理都限制在主线程中,这么做有助于防止意想不到的访问冲突产生,但也限制了线程中某些简单的UI交互的实现,比如QMessageBox。

因为QMessageBox必须在主线程中打开,为了使用它,便不得不自己动手实现一些信号和槽,从而增加了自己代码的复杂度。为降低使用QMessageBox时的设计负担,本文从QThread类继承一个新类MsgBoxThread,将这些实现细节封装为MsgBoxThread的成员函数about、aboutQt、critical、information、question、warning,分别与QMessageBox的静态成员about、aboutQt、critical、information、question、warning对应,使用时可从该类继承子类,并在run函数中使用这些函数:

#include <QThread>
#include <QMessageBox> class MsgBoxThread : public QThread
{
Q_OBJECT
typedef enum {
mbt_about = ,
mbt_aboutqt = ,
mbt_critical = ,
mbt_information = ,
mbt_question = ,
mbt_warning =
} MSGBOXTYPE;
protected:
int m_btnres;
void about(QWidget * parent, const QString &title, const QString &text) {
emit msgbox_sig(mbt_about, parent, title, text, QMessageBox::NoButton, QMessageBox::NoButton);
} void aboutQt(QWidget *parent, const QString &title = QString()) {
emit msgbox_sig(mbt_aboutqt, parent, title, tr(""), QMessageBox::NoButton, QMessageBox::NoButton);
} int critical(QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons defaultButton = QMessageBox::NoButton) {
emit msgbox_sig(mbt_critical, parent, title, text, buttons, defaultButton);
return m_btnres;
} int information(QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons defaultButton = QMessageBox::NoButton)
{
emit msgbox_sig(mbt_information, parent, title, text, buttons, defaultButton);
return m_btnres;
} int question(QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No), QMessageBox::StandardButtons defaultButton = QMessageBox::NoButton) {
emit msgbox_sig(mbt_question, parent, title, text, buttons, defaultButton);
return m_btnres;
} int warning(QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons defaultButton = QMessageBox::NoButton) {
emit msgbox_sig(mbt_warning, parent, title, text, buttons, defaultButton);
return m_btnres;
} public:
MsgBoxThread(QObject * parent = )
:QThread(parent), m_btnres(QMessageBox::NoButton) {
qRegisterMetaType<QMessageBox::StandardButtons>("QMessageBox::StandardButtons");
connect(this, SIGNAL(msgbox_sig(MSGBOXTYPE, QWidget *, const QString, const QString, QMessageBox::StandardButtons, QMessageBox::StandardButtons)), SLOT(on_information(MSGBOXTYPE, QWidget *, const QString , const QString, QMessageBox::StandardButtons , QMessageBox::StandardButtons )), Qt::BlockingQueuedConnection);
}
signals:
void msgbox_sig(MSGBOXTYPE type, QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButtons defaultButton); private slots:
void on_msgbox(MSGBOXTYPE type, QWidget * parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButtons defaultButton) {
switch(type) {
case mbt_about:
QMessageBox::about(parent,title,text);
break;
case mbt_aboutqt:
QMessageBox::aboutQt(parent, title);
break;
case mbt_critical:
m_btnres = QMessageBox::critical(parent, title, text, buttons, defaultButton);
break;
case mbt_information:
m_btnres = QMessageBox::information(parent, title, text, buttons, defaultButton);
break;
case mbt_question:
m_btnres = QMessageBox::question(parent, title, text, buttons, defaultButton);
break;
case mbt_warning:
m_btnres = QMessageBox::warning(parent, title, text, buttons, defaultButton);
break;
default:
Q_ASSERT_X(false,"QMessageBox in thread","invalid box type specified.");
}
}
};

原理:

自定义的MsgBoxThread类继承自QThread类,其中声明了可在子线程中发射的信号msgbox_sig,并在MsgBoxThread的构造函数中将该信号以阻塞模式(Qt::BlockingQueuedConnection)连接到私有槽函数on_msgbox。因为槽函数的父对象在主线程中创建,这保证了信号msgbox_sig在主线程的事件循环中执行;又由于槽函数on_msgbox采用组色模式连接,使得子线程在调用了这些封装函数(about、aboutQt、information、critical、warning)后会等待主线程的槽函数执行并返回后才会继续执行;综上,即可保证使用QMessageBox实现简单的UI交互,又不违反Qt的GUI相关处理必须在主线程中的限制。

参考:http://blog.csdn.net/johnyork/article/details/46419185

关于Qt在子线程中使用QMessageBox的折衷方法的更多相关文章

  1. MFC在子线程中创建窗口(PostMessage方法)

    1.创建子线程 C++创建线程的方式比较多 1)最简单易用的<thread>头文件,但是这种方法创建的子线程中无法给主线程PostMessage消息(也可能是我操作有误,总之没成功) 2) ...

  2. Android在子线程中更新UI(二)

    MainActivity如下: package cc.testui2; import android.os.Bundle; import android.view.View; import andro ...

  3. 子线程中刷新了UI

    This application is modifying the autolayout engine from a background thread, which can lead to engi ...

  4. 【转载】Delphi7从子线程中发送消息到主线程触发事件执行

    在对数据库的操作时,有时要用一个子线程来进行后台的数据操作.比如说数据备份,转档什么的.在主窗口还能同是进行其它操作.而有时后台每处理一个数据文件,要向主窗口发送消息,让主窗口实时显示处理进度在窗口上 ...

  5. 在子线程中new Handler报错--Can't create handler inside thread that has not called Looper.prepare()

    在子线程中new一个Handler为什么会报以下错误? java.lang.RuntimeException:  Can't create handler inside thread that has ...

  6. 如何在子线程中使用Toast和更新UI

    因为没一个Looper处理消息循环,所以子线程中无法使用Toast 方法: Looper.prepare(); Toast.makeText(getActivity(),"刷到底啦" ...

  7. 在子线程中使用runloop,正确操作NSTimer计时的注意点 三种可选方法

    一直想写一篇关于runloop学习有所得的文章,总是没有很好的例子.游戏中有一个计时功能在主线程中调用: 1 + (NSTimer *)scheduledTimerWithTimeInterval:( ...

  8. 让NSURLConnection在子线程中运行

    可以有两个办法让NSURLConnection在子线程中运行,即将NSURLConnection加入到run loop或者NSOperationQueue中去运行. 前面提到可以将NSTimer手动加 ...

  9. iOS多线程的初步研究(五)-- 如何让NSURLConnection在子线程中运行

    可以有两个办法让NSURLConnection在子线程中运行,即将NSURLConnection加入到run loop或者NSOperationQueue中去运行. 前面提到可以将NSTimer手动加 ...

随机推荐

  1. VC6项目移植到VS2008的若干问题——好的代码,从我做起,从如今做起。

    近期,有个项目开发,须要用到曾经项目的代码,只是曾经项目都是VC6下编译通过的,在VS2008下不一定编译通过,能编译通过也不一定能链接成功.以下总结一下我在一个VC6项目移植到VS2008中遇到的一 ...

  2. 基于 Quartz 开发企业级任务调度应用--转

    Quartz 基本概念及原理 Quartz Scheduler 开源框架 Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现.该项目于 2009 ...

  3. [转] GCC __builtin_expect的作用

    http://blog.csdn.net/shuimuniao/article/details/8017971 将流水线引入cpu,可以提高cpu的效率.更简单的说,让cpu可以预先取出下一条指令,可 ...

  4. Android(java)学习笔记232:Android进程间通讯(IPC)之AIDL

    一.IPC inter process communication  进程间通讯 二.AIDL android  interface  defination  language  安卓接口定义语言 满 ...

  5. 7-http1.1和2.0的区别?

    1.多路复用:减少tcp请求 合并成一个2.首部压缩:会把多个首部压缩3.服务器推送:不用request也可以response

  6. GridView点击行,选中模版列中CheckBox

    <asp:TemplateField ItemStyle-Width="40px" HeaderText="选择" ItemStyle-Horizonta ...

  7. .Net程序员 Solr-5.3之旅 (一)Solr入门

    阅读目录 引言 Lunece是什么? Solr是什么 JAVA环境搭建 JAVA环境搭建之变量配置 Tomcat简单配置 结尾 引言 君子生非异也,善假于物也. Java和.Net哪个好,我们也不需要 ...

  8. 使用<pre>标签为你的网页加入大段代码

    在上节中介绍加入一行代码的标签为<code>,但是在大多数情况下是需要加入大段代码的,如下图: 怎么办?不会是每一代码都加入一个<code>标签吧,没有这么复杂,这时候就可以使 ...

  9. Swift 提示 error running playground...

    创建playground之后,我们将得到一个错误提示,Error running playground: Failed to prepare for communication with playgr ...

  10. cas sso单点登录系列6_cas单点登录防止登出退出后刷新后退ticket失效报500错

    转(http://blog.csdn.net/ae6623/article/details/9494601) 问题: 我登录了client2,又登录了client3,现在我把client2退出了,在c ...