版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/GoForwardToStep/article/details/53667566

一、简述

先简单介绍一下模态与非模态对话框。

模态对话框

简单一点讲就是在弹出模态对话框时,除了该对话框整个应用程序窗口都无法接受用户响应,处于等待状态,直到模态对话框被关闭。这时一般需要点击对话框中的确定或者取消等按钮关闭该对话框,程序得到对话框的返回值(即点击了确定还是取消),并根据返回值进行相应的操作,之后将操作权返回给用户。这个时候用户可以点击或者拖动程序其他窗口。

说白了就相当于阻塞同一应用程序中其它可视窗口的输入的对话框,用户必须完成这个对话框中的交互操作并且关闭了它之后才能访问应用程序中的其它窗口。

其实模态对话框的作用就是得到用户选择的结果,根据结果来进行下面的操作。

非模态对话框

又叫做无模式对话框,即弹出非模态对话框时,用户仍然可以对其他窗口进行操作,不会因为这个对话框未关闭就不能操作其他窗口。

半模态对话框

半模态对话框区别于模态与非模态对话框,或者说是介于两者之间,也就是说半模态对话框会阻塞窗口的响应,但是不会影响后续代码的执行。

Qt中的模态&非模态&半模态

QWidget

QWidget提供了setWindowModality()方法设置窗口半模态or非模态;

Qt::NonModal The window is not modal and does not block input to other windows.

非模态对话框

Qt::WindowModal The window is modal to a single window hierarchy and blocks input to its parent window, all grandparent windows, and all siblings of its parent and grandparent windows.

窗口级模态对话框,即只会阻塞父窗口、父窗口的父窗口及兄弟窗口。(半模态对话框)

Qt::ApplicationModal The window is modal to the application and blocks input to all windows.

应用程序级模态对话框,即会阻塞整个应用程序的所有窗口。(半模态对话框)

Qt助手中的show()方法——非模态对话框

Qt助手中的介绍很简单,就是显示窗口以及他的子窗口。

Qt助手中的setWindowModality()方法

setWindowModality()方法可以设置窗口是否是模态窗口,从上图中我们可以看到Qt::WindowModality的默认值为Qt::NonModal,也就是非模态窗口。

所以,如果没有设置Qt::WindowModality属性值,我们每次用show()方法显示出的窗口都是非模态窗口。

QDialog

我们知道QWidget是大部分 控件的父类,也就是说QWidget是控件的始祖类,处于最上层,而QDialog也继承自QWidget。

在Qt助手中我们发现在QDialog除了继承QWidget的show()方法外,多了两个方法用来显示窗口,分别是open() 和 exec()方法。

Qt助手中的open()方法——半模态对话框

可以看到使用open()方法显示出的对话框为窗口级模态对话框,并且立即返回,这样open()方法后的代码将会继续执行。open()方法就相当于如下代码。

void showWindow()

{

QWidget* pWindow = new QWidget();

QWidget* childWindow = new QWidget(pWindow);

childWindow->setWindowModality(Qt::WindowModal);

childWindow->show();

// 上面三行代码相当于下面两行代码;

//QDialog* childDialog = new QDialog(pWindow);

//childDialog->open();

// 下面的代码可以执行;

qDebug() << "这是一个半模态窗口";

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Qt助手中的exec()方法——模态对话框

可以看到使用exec()方法显示出的对话框为模态对话框,同时会阻塞之前窗口的响应直到用户关闭这个对话框,并且返回DialogCode(包括Accepted和Rejected两个值)结果。

看红色划线部分,如果没有设置Qt::WindowModality属性值,使用exec()方法显示出的对话框默认为应用程序级模态对话框。所有使用exec()方法显示对话框在窗口关闭前会阻塞整个程序所有窗口的响应。同时调用exec()方法后的代码也不会执行直到对话框关闭才会继续执行。在关闭对话框后exec()方法会返回Accepted或者Rejected,一般程序根据返回不同的结果进行相应的操作。

那我们是否可以用以下代码来代替QDialog中的exec()方法呢?

void showModalWindow()

{

QWidget* pWindow = new QWidget();

QWidget* childWindow = new QWidget(pWindow);

childWindow->setWindowModality(Qt::ApplicationModal);

childWindow->show();

// 下面的代码可以执行;

qDebug() << "这是一个模态窗口吗?";

}

1

2

3

4

5

6

7

8

9

10

11

显然是不可以的,这里调用完show()方法后立即返回了,并不知道用户选择了Accepted还是Rejected。而exec()会阻塞后面代码的执行,直到对话框关闭,返回结果。

下面用QDialog的exec()方法来显示一个模态对话框。

void showModalWindow()

{

QWidget* pWindow = new QWidget();

QDialog* childDialog = new QDialog(pWindow);

int resutl = childDialog ->exec();

if (resutl == QDialog::Accepted)

{

qDebug() << "You Choose Ok";

}

else

{

qDebug() << "You Choose Cancel";

}

// 在关闭对话框之后,下面的代码才可以执行;

qDebug() << "这是一个模态窗口";

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

模式对话框有自己的事件循环。按照我的理解,实际上 exec() 方法是先设置modal属性为Qt::ApplicationModal,然后调用 show() 显示对话框,最后启用事件循环来阻止exec() 方法的结束。直到窗口关闭,得到返回结果(DialogCode),退出事件循环,最后exec()方法调用结束,exec()方法后的代码将继续执行。

QDialog的exec() 方法的实现 整体上就是按照上方所讲的思路进行实现的。关于exec() 方法返回的结果可以通过对界面上的按钮绑定相应的槽,比如确定按钮绑定accept()槽,取消按钮绑定reject()槽,这样在点击确定或者取消按钮时exec()方法就会返回Accepted 或者 Rejected,可以根据返回的值做出相应的操作。

下面就直接上代码实现exec()方法。

二、代码之路

实现QDialog的exec()方法

void MyDialog::init()

{

connect(ui.pButtonOk, SIGNAL(clicked()), this, SLOT(onOkClicked()));

connect(ui.pButtonCancel, SIGNAL(clicked()), this, SLOT(onCancelClicked()));

}

int MyDialog::exec()

{

// 设置为模态;

this->setWindowModality(Qt::ApplicationModal);

show();

// 使用事件循环QEventLoop ,不让exec()方法结束,在用户选择确定或者取消后,关闭窗口结束事件循环,并返回最后用户选择的结果;

// 根据返回结果得到用户按下了确定还是取消,采取相应的操作。从而模拟出QDialog类的exec()方法;

m_eventLoop = new QEventLoop(this);

m_eventLoop->exec();

return m_chooseResult;

}

void MyDialog::onOkClicked()

{

m_chooseResult = Accepted;

close();

}

void MyDialog::onCancelClicked()

{

m_chooseResult = Rejected;

close();

}

void MyDialog::closeEvent(QCloseEvent *event)

{

// 关闭窗口时结束事件循环,在exec()方法中返回选择结果;

if (m_eventLoop != NULL)

{

m_eventLoop->exit();

}

event->accept();

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

三、 Qt事件循环的一些理解(exec、eventloop)

1、事件循环一般用exec()函数开启。QApplicaion::exec()、QMessageBox::exec()都是事件循环。其中前者又被称为主事件循环。

事件循环首先是一个无限“循环”,程序在exec()里面无限循环,能让跟在exec()后面的代码得不到运行机会,直至程序从exec()跳出。从exec()跳出时,事件循环即被终止。QEventLoop::quit()能够终止事件循环。

其次,之所以被称为“事件”循环,是因为它能接收事件,并处理之。当事件太多而不能马上处理完的时候,待处理事件被放在一个“队列”里,称为“事件循环队列”。当事件循环处理完一个事件后,就从“事件循环队列”中取出下一个事件处理之。当事件循环队列为空的时候,它和一个啥事也不做的永真循环有点类似,但是和永真循环不同的是,事件循环不会大量占用CPU资源。

事件循环的本质就是以队列的方式再次分配线程时间片。

2、事件循环是可以嵌套的,一层套一层,子层的事件循环执行exec()的时候,父层事件循环就处于中断状态;当子层事件循环跳出exec()后,父层事件循环才能继续循环下去。

另外,子层事件循环具有父层事件循环的几乎所有功能。Qt会把事件送到当前生效的那个事件循环队列中去,其中包括Gui的各种事件。所以用户在主线程中执行各种exec()(如QMessageBox::exec(),QEventLoop::exec())的时候,虽然这些exec()打断了main()中的QApplication::exec(),但是Gui界面仍然能够正常响应。

3、如果某个子事件循环仍然有效,但其父循环被强制跳出,此时父循环不会立即执行跳出,而是等待子事件循环跳出后,父循环才会跳出。

摘自 http://blog.chinaunix.net/uid-27685749-id-3847998.html。

关于模态、非模态、半模态窗口的定义也很好理解,其实也就是跟用户操作过程中进行交互的问题。

同时我们也通过简单的代码来模拟出了QDialog的exec()方法。有问题直接找Qt助手,在这里基本上便能找到我们需要的答案。所以说遇到一些问题不一定非要立马到网上找各种资料或者到学习群中询问问题的解决办法,多看看帮助问题还是很有好处的。

http://www.kuqin.com/qtdocument/classes.html , 这个网址里提供了Qt文档的中文翻译 ,有需要的小伙伴可以看看。

————————————————

版权声明:本文为CSDN博主「前行中的小猪」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/GoForwardToStep/article/details/53667566

java 非模态_Qt 之 模态、非模态、半模态窗口的介绍及 实现QDialog的exec()方法相关推荐

  1. Qt模态对话框/非模态对话框/半模态对话框

    模态对话框 阻塞同一应用程序中其它可视窗口输入的对话框: 显示模态对话框最常见的方法是调用其exec()函数: #pragma execution_character_set("utf-8& ...

  2. 变分模态分解 python_浅谈VMD(变分模态分解)

    学号:19011210554   姓名:袁博 [嵌牛导读]:好多人看着VMD看博客最想知道的就是这东西的应用和大概步骤原理,而具体原理算法不太感兴趣,而且也不太容易看懂.本文既然是浅谈,就讲解一下VM ...

  3. matlab 模态叠加法,基础激励下基于模态叠加法谐响应分析.doc

    基础激励下基于模态叠加法谐响应分析 基础激励下基于模态叠加法谐响应分析 摘要: 针对ANSYS等商业有限元软件无法进行基础激励下基于模态叠加法的谐响应分析的问题,将以绝对响应为变量的动力学方程改写为基 ...

  4. 禁用引导模态区域之外的单击以关闭模态

    本文翻译自:Disable click outside of bootstrap modal area to close modal I am making a bootstrap website, ...

  5. java接口有非抽象方法_[Java教程]纳尼,java可以在接口中实现非抽象方法了?

    [Java教程]纳尼,java可以在接口中实现非抽象方法了? 0 2016-09-17 18:00:20 纳尼,接口中可以定义实例方法了?! 纳尼,接口中还可以定义静态方法了?! 没错,在Java8中 ...

  6. Java多线程:线程安全和非线程安全的集合对象

    转载自  Java多线程:线程安全和非线程安全的集合对象 一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到 ...

  7. 理解Java里面的必检异常和非必检异常

    问题:理解Java里面的必检异常和非必检异常 Joshua Bloch在"Effective Java"里面说过 在可恢复的条件下和编程错误导致的运行时错误时,使用必检异常(第二版 ...

  8. zbb20180913 java synchronized同步静态方法和同步非静态方法的异同

    java synchronized同步静态方法和同步非静态方法的异同 所有的非静态同步方法用的都是同一把锁--实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步 ...

  9. 浅谈 JAVA中静态初始化块和非静态初始化块的区别

    众所周知在JAVA编程语言中有两种初始化块: 静态初始化块 非静态初始化块 他们到底有什么区别呢?今天就浅谈一下JAVA中静态初始化块和非静态初始化块的区别 静态初始化块 定义: static{} 执 ...

最新文章

  1. 2022-2028年中国激光脱毛仪行业市场调查研究报告
  2. JavaSE基础知识(5)—面向对象(5.2类的成员)
  3. 【转】使用Navicat for Oracle新建表空间、用户及权限赋予
  4. Android之自定义带圆角的水纹波效果
  5. figure字体 latex_Latex字体大小和样式
  6. S35VB100-ASEMI日本新电元平替整流桥S35VB100
  7. html css 美化模板,通用css样式,全局css样式,css样式模板,
  8. Adobe Flash Player 地区不相容的解决方法
  9. 如何修复计算机的无限功能,Win10系统自动修复时出现无限死循环或提示无法修复怎么办 如何禁用自动修复服务...
  10. 全球及中国手机SAW滤波器行业供需现状及盈利前景预测报告(新版)2022-2027
  11. 微信小程序开发-多条件搜索tab展示
  12. supervisor+cesi多服务器进程集中管理
  13. keep-alive 的详细介绍
  14. ERTEC200P-2 PROFINET设备完全开发手册(目录)
  15. 一步入天象 eclipce 本地maven搭建
  16. 腾讯云轻量应用服务器配置表汇总2核2G/2核4G/4核8G/8核16G!
  17. 创新驱动国产介入医疗设备崛起 唯迈医疗携极光平板DSA亮相新疆介入放射学年会
  18. 国内国外主流的CMS
  19. html做qqdiy名片源码,QQ DIY名片自定义
  20. java触发器时间_Java 时间触发器

热门文章

  1. 分离内核和虚拟机支持安全的关键任务边缘计算
  2. 自然语言推理和数据集
  3. 基于TensorRT车辆实时推理优化
  4. 2021年大数据Hadoop(七):HDFS分布式文件系统简介
  5. Django 上传图片和Admin站点5.2
  6. MySQL 学习笔记(18)— 索引的分类、创建、查看、删除等
  7. Python 类对象及属性内置方法 classmethod、delattr、dir、hasattr、getattr、callable
  8. 使用jdk生成ssl证书文件
  9. 十六.监控系统cpu.内存,磁盘等,自动报警,发送邮件
  10. GIT入门笔记(4)- GIT 安装