转载自: http://www.360doc.com/content/15/0825/16/20016257_494656595.shtml
在Qt中QDialog为“窗口”,而QWidget为“部件”,首先还是了解下《Qt 窗口与部件的概念》。
对于 QDialog 的模态及非模态是直接可以实现的,很多课本中都会提到,此处总结下。
模态QDialog
方式一:
方式二:QDialog dlg(this); dlg.exec();
非模态QDialogQDialog *pDlg=new QDialog(this); pDlg->setModal(true); pDlg->show();
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()的(具体看源码)!