QDialog 模态对话框与事件循环(exec其实就是调用了show和eventLoop.exec)
起源
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)的更多相关文章
- 事件循环和线程没有必然关系(就像Windows子线程默认没有消息循环一样),模态对话框和事件循环也没有必然关系(QWidget直接就可以)
周末天冷,索性把电脑抱到床上上网,这几天看了 dbzhang800 博客关于 Qt 事件循环的几篇 Blog,发现自己对 Qt 的事件循环有不少误解.从来只看到现象,这次借 dbzhang800 的博 ...
- MFC模态对话框的消息循环
MFC模态对话框的消息循环 单线程程序, 当主窗口响应函数中弹出模态对话框时,为什么主窗口响应函数可能照常工作? 当弹出模态对话框时,线程的消息循环无法返回,父窗口的事件本应没人处理,应该处于卡死状态 ...
- 乱谈Qt事件循环嵌套
本文旨在说明:QDialog::exec().QMenu::exec()等开启的局部事件循环,易用的背后,还有很多的陷阱... 引子 Qt 是事件驱动的,基本上,每一个Qt程序我们都会通过QCoreA ...
- Qt 的线程与事件循环——可打印threadid进行观察槽函数到底是在哪个线程里执行,学习moveToThread的使用)
周末天冷,索性把电脑抱到床上上网,这几天看了 dbzhang800 博客关于 Qt 事件循环的几篇 Blog,发现自己对 Qt 的事件循环有不少误解.从来只看到现象,这次借 dbzhang800 的博 ...
- 局部QEventLoop帮助QWidget不消失(也就是有一个局部事件循环始终在运行,导致程序被卡住那里,但仍可以接受事件。说白了就是有一个while语句死活不肯退出,直到收到退出信号)
熟悉的陌生人 Qt 是事件驱动的,所以当你用Qt的时候,几乎时时刻刻和 QEventLoop 打交道.,只是你可能没有意识到: QCoreApplicaton::exec() QApplication ...
- 深入理解QStateMachine与QEventLoop事件循环的联系与区别
最近一直在倒腾事件循环的东西,通过查看Qt源码多少还是有点心得体会,在这里记录下和大家分享.总之,对于QStateMachine状态机本身来说,需要有QEventLoop::exec()的驱动才能支持 ...
- Qt 学习之路:线程和事件循环
前面一章我们简单介绍了如何使用QThread实现线程.现在我们开始详细介绍如何“正确”编写多线程程序.我们这里的大部分内容来自于Qt的一篇Wiki文档,有兴趣的童鞋可以去看原文. 在介绍在以前,我们要 ...
- Qt事件机制浅析(定义,产生,异步事件循环,转发,与信号的区别。感觉QT事件与Delphi的事件一致,而信号则与Windows消息一致)
Qt事件机制 Qt程序是事件驱动的, 程序的每个动作都是由幕后某个事件所触发.. Qt事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. Qt事件的类型很多, 常见的qt的事件如下: 键盘事 ...
- Qt ------ 再论事件循环
在介绍在以前,我们要认识两个术语: 可重入的(Reentrant):如果多个线程可以在同一时刻调用一个类的所有函数,并且保证每一次函数调用都引用一个唯一的数据,就称这个类是可重入的(Reentrant ...
随机推荐
- UNION ALL vs UNION
一直没意识到它们之间的区别,只知道UNION ALL在性能上优于UNION,忽略一个很重要的区别:UNION会去掉重复的行,而UNION ALL是包括所有行.
- HDU-1978How many ways
Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下:1.机器人一开始在棋盘的起始点并有起始点所标有 ...
- JAVA 对象拷贝
1.java里的clone分为: A:浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. b:深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍. Java中对 ...
- ubantu14.04 apache2 支持重写模式
想要开启thinkphp的重写模式,apache必须.htaccess支持, 其他情况也有需要开启.htaccess支持的. 下面是ubantu开启方法: 0. .htaccess这个文件应该放在与入 ...
- git 错误
1 执行 Git add somefile 的时候,出现 如下 错误: If no other git process is currently running, this probably m ...
- 使用GCM服务(Google Cloud Messaging)实现Android消息推送
最近在网上查了关于很多Android消息推送的资料,其中主要有四种方法. 1) 使用GCM服务(Google Cloud Messaging) 2) 使用XMPP协议(Openfire + Spark ...
- Quartz中时间表达式的设置-----corn表达式
Quartz中时间表达式的设置-----corn表达式 时间格式: <!-- s m h d m w(?) y(?) -->, 分别相应: 秒>分>小时>日>月 ...
- 秀才每天一篇之—SEO是什么?
[导读]SEO是什么?秀才搁笔七天以来.遇到非常多事情.站点被K ,排名掉了. 却找不出原因,開始迷茫了.以至于没有心情来照应这个博客,不好意思了,各位.在这七天以来.秀才一直在思考,SEO究竟应该怎 ...
- CAsyncSocket
本词条缺少名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! 它是一个异步非阻塞Socket封装类,CAsyncSocket::Create()有一个参数指明了你想要处理哪些Socket事 ...
- Android 基于Netty的消息推送方案之Hello World(一)
消息推送方案(轮询.长连接) 轮询 轮询:比较简单的,最容易理解和实现的就是客户端去服务器上拉信息,信息的及时性要求越高则拉信息的频率越高.客户端拉信息的触发可以是一些事件,也可以是一个定时器,不断地 ...