天天看點

QT中模态對話框與非模态對話框

此文來源于網絡上的知識,經過我的整理,有錯的話希望大家及時指出喔,友善大家學習交流。

對話框在QtGUI應用程式中有着廣泛的用途,對話框有模态、非模态兩種情況。對于參數選擇的對話框,一般用模态對話框;對于顯示或檢視某些内容的對話框,一般用非模态對話框。模态對話框(Modal Dialog)與非模态對話框(Modeless Dialog)的概念不是Qt所獨有的,在各種不同的平台下都存在。又有叫法是稱為模式對話框,無模式對話框等。 

二者的差別:模态對話框就是指在子對話框彈出時,焦點被強行集中于該子對話框,子對話框不關閉,使用者将無法操作其他的視窗。非模态相反,使用者仍然可以操作其他的視窗,包括該子對話框的父對話框。如果從線程角度來講,模态對話框實際上是線程阻塞的,也就是子對話框是一個線程,但是在建立這個子線程之後,父視窗就阻塞了;模态對話框則不是阻塞型的線程模型,父子線程可以并行運作。 

在Qt中,顯示一個對話框一般有兩種方式,一種是使用exec()方法,它總是以模态來顯示對話框;另一種是使用show()方法,它使得對話框既可以模态顯示,也可以非模态顯示,決定它是模态還是非模态的是對話框的modal屬性。一般使用setModal()方法來設定對話框的modal屬性。 

在Qt中,Qt的模态與非模态對話框選擇是通過其屬性modal來确定的。我們來看看modal屬性,其定義如下:modal : bool預設情況下,對話框的該屬性值是false,這時通過show()方法顯示的對話框就是非模态的。而如果将該屬性值設定為true,就設定成了模态對話框,其作用于把QWidget::windowModality屬性設定為Qt::ApplicationModal。而使用exec()方法顯示對話框的話,将忽略modal屬性值的設定并把對話框設定為模态對話框。(其實在exec()函數内部已經封裝了設定為模态對話框的語句)

◆ 如果要設定為模态對話框,最簡單的就是使用exec()方法,示例代碼如下:
     MyDialog myDlg;
     myDlg.exec();
     也可以使用show()方法,示例代碼如下:
     MyDialog myDlg;
     myDlg.setModal(true);
     myDlg.show();
     ◆ 如果要設定為非模态對話框,必須使用show()方法,示例代碼如下:
     MyDialog myDlg;
     myDlg.setModal(false);//或者myDlg.setModal();
     myDlg.show();      

附注1:exec()函數的傳回值

在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函數的傳回值來判斷使用者點選了哪個按鈕使得模态對話框退出的,這可以使得我們能夠根據使用者的不同行為在退出模态對話框之後采取不同的處理方法。 

附注2:對話框關閉處理記憶體問題

在Qt中建立非模态對話框,主要用到了QDialog的show函數:

SonDialog *dlg;
dlg = new SonDialog(this);
dlg->show();      

由上面代碼,細心的讀者可能就會問了,既然new了,如果不delete,那麼記憶體不就存在了洩露的問題了嗎?确實如此!是以,我們希望該Qt視窗在退出時自動能夠delete掉自己,是以,我們在SonDialog的構造函數裡,添加這樣的一句代碼:

setAttribute (Qt::WA_DeleteOnClose);

這樣,我們的SonDialog就能夠在它退出時自動的delete掉自己了,不會再造成記憶體洩漏問題。 

附注3:視窗如何保持在最前面

有時候,我們需要一個對話框以非模态的形式顯示,但又需要它總在所有視窗的最前面,這時可以通過如下代碼設定:

MyDialog myDlg;
myDlg.setModal(false);//或者myDlg.setModal();
myDlg.show();
//關鍵是下面這行
myDlg.setWindowFlags(Qt::WindowStaysOnTopHint);