QT模态对话框及非模态对话框

模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在。又有叫法是称为模式对话框,无模式对话框等。所谓模态对话框就是在其没有被关闭之前,用户不能与同一个应用程序的其他窗口进行交互,直到该对话框关闭。对于非模态对话框,当被打开时,用户既可选择和该对话框进行交互,也可以选择同应用程序的其他窗口交互。

Qt中,显示一个对话框一般有两种方式,一种是使用exec()方法,它总是以模态来显示对话框;另一种是使用show()方法,它使得对话框既可以模态显示,也可以非模态显示,决定它是模态还是非模态的是对话框的modal属性。

Qt中,Qt模态非模态对话框选择是通过其属性modal来确定的。我们来看看modal属性,其定义如下:

modal : bool默认情况下,对话框的该属性值是false,这时通过show()方法显示的对话框就是非模态的。而如果将该属性值设置为true,就设置成了模态对话框,其作用于把QWidget::windowModality属性设置为Qt::ApplicationModal。

而使用exec()方法显示对话框的话,将忽略modal属性值的设置并把对话框设置为模态对话框。

一般使用setModal()方法来设置对话框的modal属性。

我们总结一下设置对话框为模态的方法。

◆ 如果要设置为模态对话框,最简单的就是使用exec()方法,示例代码如下:

MyDialog myDlg;    myDlg.exec();也可以使用show()方法,示例代码如下:

MyDialog myDlg;    myDlg.setModal(true);    myDlg.show();

◆  如果要设置为非模态对话框,必须使用show()方法,示例代码如下:

MyDialog myDlg;    myDlg.setModal(false);
//或者
myDlg.setModal();
myDlg.show();
再次强调,目前有的朋友对于模态对话框和非模态对话框的认识有误解,认为使用show()方法显示的就是非模态对话框,这是不正确的。

小贴士:有时候,我们需要一个对话框以非模态的形式显示,但又需要它总在所有窗口的最前面,这时可以通过如下代码设置:

MyDialog myDlg;    myDlg.setModal(false);
//或者
myDlg.setModal();    myDlg.show();
//关键是下面这行
myDlg.setWindowFlags(Qt::WindowStaysOnTopHint);

Qt中创建模态对话框,主要用到了QDialog的exec函数:
SonDialog dlg(this);
int res = dlg.exec();
if (res == QDialog::Accepted)
{
QMessageBox::information(this, “INFORMATION”, “You clicked OK button!”);
}
if (res == QDialog::Rejected)
{
QMessageBox::information(this, “INFORMATION”, “You clicked CANCEL button!”);
}
正如上面代码所显示的,可以通过exec函数的返回值来判断用户点击了哪个按钮使得模态对话框退出的,这可以使得我们能够根据用户的不同行为在退出模态对话框之后采取不同的处理方法。

既然new了,如果不delete,那么内存不就存在了泄露的问题了吗?确实如此!所以,我们希望该Qt窗口在退出时自动能够delete掉自己,因此,我们在SonDialog的构造函数里,添加这样的一句代码:

setAttribute (Qt::WA_DeleteOnClose);
这样,我们的SonDialog就能够在它退出时自动的delete掉自己了,不会再造成内存泄漏问题

Qt中存在“窗口”与“部件”的区分,但“窗口”的概念太过浅显,以至于可以忽略不谈。但有时候还是多少有些了解为好。

很多书上说,Qt中吧没有嵌入到其他部件中的部件成为“窗口”,而这种“窗口”都包含有边框和标题栏。“窗口”就是没有父窗口(或部件)的部件,又称为顶级部件。但在实际开发过Qt程序的工程师看来,这种说法有点欠佳。“窗口是没有嵌入到其他部件的部件“这个好理解,但是“窗口”就是没有父部件的部件?QDialog为窗口是毋庸置疑的吧,但是在使用对话框时为其指定父窗口也是在正常不过了。例如,当我点击主窗口某个按钮时弹出个提示对话框:

QDialog dlg(this);

dlg.exec();

弹出的Dialog一样具有边框和标题栏,难道这种具有父部件的对话框就是不是窗口了?很多人难以接受吧! 所以,一个QWidget是窗体还是窗体上的控件和是否有父类无关,只与窗口标记类型有关,也只有窗口flag才能直接说明此部件是否为窗口!设置或修改部件类型:setWindowFlags(Qt::Window)

但是也无需怀疑很多书本的可靠性,其实书上说的也没错,只是不够深入。例如:

QPushButton * pPushBtn = new QPushButton(this);

//当没有父类时,构造函数就会加上Qt::Window标记
QPushButton * pPushBtn = new QPushButton;
因为,当没有指定父窗口(部件)时都是默认设置了Qt::Window标记的。再如:

//不管有无父类都为窗体,因为向QWidget传参数时传递了Qt::Dialog标记.

QDialog * dlg = new QDialog(this);

因此,QDialog是个独特的部件,无论有无指定父部件,其生来就是Window!

 
总而言之:所以使QWidget变成Window(窗体)只能使用setWindowFlags(Qt::Window); !!!在使用Qt是一般不考虑窗口的概念,较多情况下都直接使用QWidget就行了,对于自定义部件也是如此。对于之前做过VC的选手可能习惯了使用CDialog,但在Qt中QDialog却没那么受待见,熟练使用QWidget才是王道。
对于 QDialog 的模态及非模态是直接可以实现的,很多课本中都会提到,此处总结下。
 
模态QDialog
方式一:

QDialog dlg(this);
dlg.exec();

方式二:

QDialog *pDlg=new QDialog(this);
pDlg->setModal(true);
pDlg->show();

非模态QDialog

QDialog *pDlg=new QDialog(this);
pDlg->show();

 
QDialog实现模态非模态很简单,但是对于QWidget有点迷茫,QWidget中没有exec(),也没有setModal()方式,但是想想看,QWidget作为QDialog的基类,而且QWidget作为“窗口”使用也是在平常不过了,所以会意识到QWidget中是否存在一个相对exec()或setModal()更基本的操作来实现模态和非模态呢?就这样,我找到了setWindowModality(),此函数就是用来设置QWidget运行时的程序阻塞方式的,参数解释如下:
Qt::NonModal 不阻塞
Qt::WindowModal 阻塞父窗口,所有祖先窗口及其子窗口
Qt::ApplicationModal 阻塞整个应用程序
 
看来,setModal()也就是使用setWindowModality()设置Qt::ApplicationModal参数也实现的模态。
 
如此,要实现QWidget的模态和非模态,只要调用setWindowModality()设置阻塞类型就好了:
QWidget *pWid = new QWidget(this);
pWid->setWindowModality(Qt::ApplicationModal);
//pWid->setAttribute(Qt::WA_ShowModal, true);
pWid->show();

但是运行发现并未实现模态效果。这里需要注意,当希望使用setWindowModality()将QWidget设置为模态时应该保证QWidget父部件为0,这里修改QWidget *pWid = new QWidget(this);为QWidget *pWid = new QWidget(NULL);在运行就好了。

 
此外,通过setWindowModality()设置模态窗口并不是唯一方式,直接设置部件(或窗口)属性也可以:

pWid->setAttribute(Qt::WA_ShowModal, true)

---------------

还有很多地方需要注意,当创建QDialog后使用setWindowFlags(Qt::FramelessWindowHint);去掉标题栏时此对话框不再阻塞父窗口,如果需要实现阻塞效果可再次指定Qt::Dialog,即使用:
setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint); //这样就会阻塞父窗口了!
但是,这样会影响对话框的半透明(或透明)显示。使用Qt::Dialog之前半透明显示正常:
使用之后却死活不行了:

-- 不知道如何是好!

--------------
总而言之
是否是模态和QDialog 和QWidget都可以模态和非模态.exec(), show() 等函数无直接关系,只和窗口属性有关,使用以下两种方式都行:
setAttribute(Qt::WA_ShowModal, true);//属性设置
setWindowModality(Qt::ApplicationModal);//设置阻塞类型
-----------------
QDialog中的成员函数setModal(true)及exec()之所以是模态是因为他先设置了窗口属性:setAttribute()再show()的(具体看源码)!

QT模态对话框及非模态对话框的更多相关文章

  1. QT笔记之模态对话框及非模态对话框

    模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在.又有叫法是称为模式对话框,无模式对话框等.所谓模态对话框就是在其 ...

  2. MFC中模态对话框和非模态对话框的差别

    在MFC中有模态对话框和非模态对话框,那这两种有什么差别呢. 又都是用于什么场合呢. 首先,要弄清楚2种对话框是怎样创建的. 然后要弄清楚2种对话框有什么差别,可能从表面上看,模态会堵塞主对话框.可原 ...

  3. MFC编程入门之十二(对话框:非模态对话框的创建及显示)

    上一节讲了模态对话框及其弹出过程,本节接着讲另一种对话框--非模态对话框的创建及显示. 非模态对话框显示后,程序其他窗口仍然能正常运行,可以响应用户输入,还可以相互切换.上一讲中创建的Tip模态对话框 ...

  4. VC++模态对话框和非模态对话框

    MFC中有两种类型的对话框:模态对话框和非模态对话框.  模态对话框是指当其显示时,程序会暂停执行,直到关闭这个模态对话框后,才能继续执行程序中其他任务.非模态对话框是指当其显示时,允许转而执行程序中 ...

  5. VS2010/MFC对话框:非模态对话框的创建及显示

    非模态对话框的创建及显示 上一节讲了模态对话框及其弹出过程,本节接着讲另一种对话框--非模态对话框的创建及显示. 已经说过,非模态对话框显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切 ...

  6. c#中的模态对话框和非模态对话框

    模态对话框弹出窗口阻止调用窗口的所有消息响应.只有在弹出窗口结束后调用窗口才能继续.在模态窗口“关闭”后,可以读取模态窗口中信息,包括窗口的返回状态,窗口子控件的值. 非模态对话框可以在弹出窗口和调用 ...

  7. VS2010/MFC编程入门之十二(对话框:非模态对话框的创建及显示)

    上一节鸡啄米讲了模态对话框及其弹出过程,本节接着讲另一种对话框--非模态对话框的创建及显示. 鸡啄米已经说过,非模态对话框显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切换.鸡啄米会将 ...

  8. C#模态对话框和非模态对话框

    模态对话框弹出窗口阻止调用窗口的所有消息响应.只有在弹出窗口结束后调用窗口才能继续.在模态窗口“关闭”后,可以读取模态窗口中信息,包括窗口的返回状态,窗口子控件的值. 非模态对话框可以在弹出窗口和调用 ...

  9. VS2010-MFC(对话框:非模态对话框的创建及显示)

    转自:http://www.jizhuomi.com/software/162.html 前面已经说过,非模态对话框显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切换.本节会将上一讲中 ...

随机推荐

  1. .NET Core单元测试之搞死开发的覆盖率统计(coverlet + ReportGenerator )

    .NET Core单元测试之搞死开发的覆盖率统计 这两天在给项目补单元测试,dalao们要求要看一下测试覆盖率 翻了一波官方test命令覆盖率倒是有支持了,然而某个更新日志里面写着 ["Su ...

  2. (转) 理解Angular中的$apply()以及$digest()

    原文地址:http://blog.csdn.net/dm_vincent/article/details/38705099 $apply()和$digest()在AngularJS中是两个核心概念,但 ...

  3. linux设置定时任务调用接口

    1.设置目录 cd /var/spool/cron 2.编辑文件(当前登录用户,不一定是root) vim root 3.添加内容 0 0 * * * wget http://192.144.141. ...

  4. Jmeter资源监控工具ServerAgent运行原理的一些研究

    用过Jmeter的应该都了解,有个ServerAgent工具,放在linux或者windows服务器上开启服务后,在Jmeter中配置下监视器,就可以抓取到服务器的一些资源信息,抓取的主要是cpu.内 ...

  5. Java普通编程和Web网络编程准备工作

    一.工具下载 链接:https://pan.baidu.com/s/1geOdq3h 密码:pzl5 二.Java普通编程 解压下载的资料,并按readme.txt安装jdk和Eclipse. 三.J ...

  6. java计算两个日期之间的天数,排除节假日和周末

    如题所说,计算两个日期之前的天数,排除节假日和周末.这里天数的类型为double,因为该功能实现的是请假天数的计算,有请一上午假的为0.5天. 不够很坑的是每个日期都要查询数据库,感觉很浪费时间. 原 ...

  7. IDEA 破解图文教程 - 2018.9 更

    你好!这里是你要找的 IDEA 破解方法 目录     一.前言    二.IDEA 安装         2.1 下载IDEA 旗舰版         2.2 开始安装         2.3 自定 ...

  8. Hyperledger Fabric中的Identity

    Hyperledger Fabric中的Identity 什么是Identity 区块链网络中存在如下的角色:peers, orderers, client application, administ ...

  9. python3【基础】-list&tuple

    一.list概述 list (列表)是python中最常用的数据类型之一,通过列表可以对数据实现最方便的存储,修改等操作.在python3中,list支持如下方法: Help on class lis ...

  10. ssd a

    Alpha版本测试报告 (1)测试计划 测试人员 工作安排 瞿煌人 制定测试计划,撰写测试报告 周建峰 执行测试,撰写测试报告 注:测试结果Y表示通过测试,N表示未通过测试. 功能 描述 效果 测试结 ...