想让一个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://doc.qt.io/qt-4.8/qwidget.html

最新文章

  1. Lucene4.4.0 开发之排序
  2. 《JavaScript权威指南》学习笔记 第七天 DOM操作
  3. JS禁止WEB页面鼠标事件大全
  4. Go 命令之 godep
  5. Ci分开配置网站前台后台的方法
  6. HTML5学习(九)----应用程序缓存
  7. 同一個Loader對象傳入不同參數時,从数据库中查询的結果每次都一樣
  8. 如何实现数字lcd显示效果(原创)
  9. 不完全图解HTTP
  10. OpenCV 使用光流法检测物体运动
  11. java json转换(二)
  12. Debian如何永久添加静态路由
  13. spring_06装配bean_2
  14. SpringBoot使用redis缓存List<Object>
  15. Linux命令行下常用的快捷键
  16. windows 激活venv问题
  17. 解决:oracle+myBatis ResultMap 类型为 map 时,表字段类型有 Long/Blob/Clob 时报错
  18. Newtonsoft.Json 序列化器的重写
  19. Hive 外部表新增字段或者修改字段类型等不生效
  20. Ubuntu更新提示哈希和不匹配“Hash Sum mismatch”

热门文章

  1. [转]Redis 与Mysql通信
  2. 解析字典包含关键字比如ID,description等,MJExtension 框架 不能直接设置变量与其同名。
  3. codeblocks如何设置,启动后自动打开上次未关闭的workspace
  4. Servlet接口的实现类,路径配置映射,ServletConfig对象,ServletContext对象及web工程中文件的读取
  5. Topshelf组件
  6. vue webpack添加jQuery
  7. 一组西门子S7 报文
  8. Android官方教程翻译(3)——创建一个简单的用户界面
  9. 理解c#
  10. js 将json字符串转换为json对象