https://www.yuque.com/docs/share/15d717b4-d490-42de-ae9f-cd17967eca64
模態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()的