1. 程式人生 > >QDialog,QWidget實現模態及非模態

QDialog,QWidget實現模態及非模態

模態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()的