起源

qtcn中文论坛中有网友问到:

假设程序正常运行时,只有一个简单的窗体A,此时只有一个GUI主线程,在这个主线程中有一个事件循环处理窗体上的事件。当此程序运行到某阶段时,弹出一个模态窗体B(书上说模态窗体是有其自己的事件循环的),此时模态窗体B是否会有一个对应的子线程处理其事件循环?

这儿其实有两个问题:

  • 模态对话框 和 事件循环 没有必然联系
  • 事件循环 和 子线程 没有必然联系

题外:

如果进一步呢?其实我们还可以说:

  • 模态对话框 和 QDialog 没必要联系

QDialog 对话框

两种常规用法:

非模态

QDialog * dlg = new QDialog()
dlg->show();

当然,这儿用指针(即分配到heap中)不是必须的。  (有疑问?或者有时发现窗口一闪而过?那么你需要了解C、C++中变量的作用域和生存周期)

模态

QDialog dlg;
dlg.exec();

这种情况下,我们一般都是将对象分配上 stack 上,而不是heap上。

当然,你喜欢用 heap,也没问题:

Dialog * dlg = new QDialog();
dlg->exec();
delete dlg;

模态对话框

前面的 show() 与 exec() 并不是模态与非模态的区别。

想让一个Widget成为模态,我们只需要对其设置:

setAttribute(Qt::WA_ShowModal, true);

注意:这是QWidget的成员函数 ,也就是说,QWidget可以显示为模态或非模态!

setWindowModality

除了直接调用setAttribute外,QWidget 提供了一个易用的函数,来设置窗体的模态。其源码如下:

void QWidget::setWindowModality(Qt::WindowModality windowModality)
{
data->window_modality = windowModality;
// setModal_sys() will be called by setAttribute()
setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
setAttribute(Qt::WA_SetWindowModality, true);
}

注意:该函数的参数取值:NonModal、WindowModal、ApplicationModal 分别对应默认情况下的

  • QDialog::show()
  • QDialog::open()
  • QDialog::exec()

如果你没有使用QDialog::open()的需求,你可能也不需要该函数。

setModal

除了QWidget提供的成员,QDialog 提供了 setModal 的成员函数,我们看看其代码:

void QDialog::setModal(bool modal)
{
setAttribute(Qt::WA_ShowModal, modal);
}

不用解释了吧?我们要显示模态对话框,只需要类似下面的代码:

QDialog * dlg = new QDialog();
dlg->setAttribute(Qt::WA_ShowModal, true);
dlg->show();

exec()

有问题是不?为啥exec() 直接可以显示模态对话框呢?看QDialog源代码吧

int QDialog::exec()
{
Q_D(QDialog);
...
setAttribute(Qt::WA_ShowModal, true);
...
show();
...
QEventLoop eventLoop;
(void) eventLoop.exec(QEventLoop::DialogExec);
...
}

看到答案没:exec() 先设置modal属性,而后调用 show() 显示对话框,最后启用事件循环

事件循环

Qt 程序时事件驱动的,每个程序,我们需要调用 QApplication::exec() 来启用事件循环。

int QCoreApplication::exec()
{
...
QEventLoop eventLoop;
int returnCode = eventLoop.exec();
...
return returnCode;
}

用前面的 QDialog::exec() 一样,都是调用的 QEventLoop::exec()

int QEventLoop::exec(ProcessEventsFlags flags)
{
Q_D(QEventLoop);
...
while (!d->exit)
processEvents(flags | WaitForMoreEvents | EventLoopExec);
...
return d->returnCode;
}

bool QEventLoop::processEvents(ProcessEventsFlags flags)
{
Q_D(QEventLoop);
if (!d->threadData->eventDispatcher)
return false;
if (flags & DeferredDeletion)
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
return d->threadData->eventDispatcher->processEvents(flags);
}

进一步:这将调用平台相关的函数,比如在windows下

bool QGuiEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
if (!QEventDispatcherWin32::processEvents(flags))
return false;
if (configRequests) // any pending configs?
qWinProcessConfigRequests();
return true;
}

事件循环和线程没有必然的联系,事件循环可以用在QThread中,而且从Qt4.4开始,QThread的run函数默认就调用了自己的事件循环。

对与QDialog来说,当它自己的QEventLoop启用时,主程序的 QEventLoop 当然是处于暂停状态了。说到底,就是两个死循环,一个在内,一个在外,只有里面的退出后,外边的循环才会执行。不过由于两个循环执行的命令是基本一样的,都是调用并处理程序收到的各种事件,所以,可能变得不容易理解

http://blog.csdn.net/dbzhang800/article/details/6300416

QDialog 模态对话框与事件循环(exec其实就是调用了show和eventLoop.exec)的更多相关文章

  1. 事件循环和线程没有必然关系(就像Windows子线程默认没有消息循环一样),模态对话框和事件循环也没有必然关系(QWidget直接就可以)

    周末天冷,索性把电脑抱到床上上网,这几天看了 dbzhang800 博客关于 Qt 事件循环的几篇 Blog,发现自己对 Qt 的事件循环有不少误解.从来只看到现象,这次借 dbzhang800 的博 ...

  2. MFC模态对话框的消息循环

    MFC模态对话框的消息循环 单线程程序, 当主窗口响应函数中弹出模态对话框时,为什么主窗口响应函数可能照常工作? 当弹出模态对话框时,线程的消息循环无法返回,父窗口的事件本应没人处理,应该处于卡死状态 ...

  3. 乱谈Qt事件循环嵌套

    本文旨在说明:QDialog::exec().QMenu::exec()等开启的局部事件循环,易用的背后,还有很多的陷阱... 引子 Qt 是事件驱动的,基本上,每一个Qt程序我们都会通过QCoreA ...

  4. Qt 的线程与事件循环——可打印threadid进行观察槽函数到底是在哪个线程里执行,学习moveToThread的使用)

    周末天冷,索性把电脑抱到床上上网,这几天看了 dbzhang800 博客关于 Qt 事件循环的几篇 Blog,发现自己对 Qt 的事件循环有不少误解.从来只看到现象,这次借 dbzhang800 的博 ...

  5. 局部QEventLoop帮助QWidget不消失(也就是有一个局部事件循环始终在运行,导致程序被卡住那里,但仍可以接受事件。说白了就是有一个while语句死活不肯退出,直到收到退出信号)

    熟悉的陌生人 Qt 是事件驱动的,所以当你用Qt的时候,几乎时时刻刻和 QEventLoop 打交道.,只是你可能没有意识到: QCoreApplicaton::exec() QApplication ...

  6. 深入理解QStateMachine与QEventLoop事件循环的联系与区别

    最近一直在倒腾事件循环的东西,通过查看Qt源码多少还是有点心得体会,在这里记录下和大家分享.总之,对于QStateMachine状态机本身来说,需要有QEventLoop::exec()的驱动才能支持 ...

  7. Qt 学习之路:线程和事件循环

    前面一章我们简单介绍了如何使用QThread实现线程.现在我们开始详细介绍如何“正确”编写多线程程序.我们这里的大部分内容来自于Qt的一篇Wiki文档,有兴趣的童鞋可以去看原文. 在介绍在以前,我们要 ...

  8. Qt事件机制浅析(定义,产生,异步事件循环,转发,与信号的区别。感觉QT事件与Delphi的事件一致,而信号则与Windows消息一致)

    Qt事件机制 Qt程序是事件驱动的, 程序的每个动作都是由幕后某个事件所触发.. Qt事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. Qt事件的类型很多, 常见的qt的事件如下: 键盘事 ...

  9. Qt ------ 再论事件循环

    在介绍在以前,我们要认识两个术语: 可重入的(Reentrant):如果多个线程可以在同一时刻调用一个类的所有函数,并且保证每一次函数调用都引用一个唯一的数据,就称这个类是可重入的(Reentrant ...

随机推荐

  1. O - 覆盖的面积 - hdu 1255(求面积)

    分析:求一层的面积覆盖是非常简单的事情,不过多层面积覆盖应该怎么搞???也是比较简单的事情,只需要用两个变量记录就好了,一个记录覆盖一次的,一个记录覆盖两次的,就很容易解决了 ************ ...

  2. ios 限制输入长度

    ----------------UITextField限制输入的长度------------ - (BOOL)textField:(UITextField *)textField shouldChan ...

  3. java实现的23种设计模式 (个人推荐)

    http://zz563143188.iteye.com/blog/1847029 mark下,个人用,大家会也可以看看写的不错.

  4. 数组对象元素的添加,String对象,BOM对象以及文档对象的获取

    数组对象的删除有三种方法: pop();        //移除最后一个元素并返回该元素值shift();      //移除最前一个元素并返回该元素值,数组中元素自动前移splice(0,2); / ...

  5. 性能计数器自动收集-logman

    1.在桌面云测试中,往往需要模拟并发连接中服务器的性能数据,这里主要介绍如何自动收集性能数据 2.创建xxxx.bat文件,文件内容如下: logman create counter test -cf ...

  6. 性能优化之NSDateFormatter

    为什么要优化NSDateFormatter? 优化方式有哪些? 为什么要优化NSDateFormatter? 首先,过度的创建NSDateFormatter用于NSDate与NSString之间转换, ...

  7. ajax:html5上传文件,上传之前可以实现本地预览

    本主题主要涉及两个新内容: 1.上传文件(主要使用了FormData) 2.本地预览(主要使用了FileReader) html5的FormData其实就是平时的Form表单,只是html5可以直接新 ...

  8. 复合命令A等效于$a

    时间:2014.06.28 地点:基地 ------------------------------------------------------------------------------- ...

  9. mysql分表方法-----MRG_MyISAM引擎分表法

    一般来说,当我们的数据库的数据超过了100w记录的时候就应该考虑分表或者分区了,这次我来具体说说分表的一些方法.眼下我所知道的方法都是MYISAM的,INNODB怎样做分表而且保留事务和外键,我还不是 ...

  10. Java可见性机制的原理

    基本概念 可见性 当一个线程修改了共享变量时,另一个线程可以读取到这个修改后的值. 内存屏障(Memory Barriers) 处理器的一组指令,用于实现对内存操作的顺序限制. 缓冲行 CPU告诉缓存 ...