Qt中的模態、非模態、半模態窗口

作者:billy
版權聲明:著作權歸作者所有,商業轉載請聯繫作者獲得授權,非商業轉載請註明出處

簡述

  1. 模態對話框
    簡單一點講就是在彈出模態對話框時,除了該對話框,整個應用程序的窗口都無法接受用戶響應,處於等待狀態,直到模態對話框被關閉。這時一般需要用戶點擊對話框中的確定或取消按鈕來關閉該對話框,程序得到對話框的返回值,並根據返回值進行相應的操作,之後將操作權返回給用戶。這個時候用戶就可以點擊或者拖動程序其他窗口了。

  2. 非模態對話框
    非模態對話框又叫做無模式對話框,即彈出非模態對話框時,用戶仍然可以對其他窗口進行操作,不會因爲這個對話框未關閉就不能操作其他窗口。

  3. 半模態對話框
    半模態對話框區別於模態與非模態對話框,或者說是介於兩者之間,也就是說半模態對話框會阻塞窗口的響應,但是不會影響後續代碼的執行。

在Qt中我們常用的窗口有 QWidget、QMainWindow 以及 QDialog
下面我們結合Qt幫助文檔來看一下這三種窗口之間的關係,以及如何實現模態、非模態和半模態。

繼承關係

inherit
inherit
inherit
QWidget
QObjec
QMainWindow
QDialog

QWidget

QWidget類是所有用戶界面對象的基類

窗口部件是用戶界面的一個原子:它從窗口系統接收鼠標、鍵盤和其它事件,並且將自己的表現形式繪製在屏幕上。每一個窗口部件都是矩形,並且它們按Z軸順序排列。一個窗口部件可以被它的父窗口部件或者它前面的窗口部件蓋住一部分。

  1. show()
    QWidget的顯示是通過 show() 方法來實現的,查看幫助文檔可以看到
    在這裏插入圖片描述
    介紹的比較簡單,只是說明了顯示窗口以及他的子窗口。這裏需要注意的是,通過 show() 方法顯示的 QWidget 是非模態對話框

  2. setWindowModality()
    QWidget提供了 setWindowModality() 方法來設置窗口爲模態或非模態
    在這裏插入圖片描述
    setWindowModality() 方法可以設置窗口是否是模態窗口,從上圖中我們可以看到Qt::WindowModality的默認值爲Qt::NonModal,也就是非模態窗口。所以如果沒有設置Qt::WindowModality屬性值,我們每次用 show() 方法顯示出的窗口都是非模態窗口。

QMainWindow

QMainWindow類提供一個有菜單條、工具欄、狀態條的主應用程序窗口

一個主窗口提供了構建應用程序的用戶界面框架。Qt擁有QMainWindow及其相關類來管理主窗口。QMainWindow擁有自己的佈局,我們可以使用QMenuBar(菜單欄)、QToolBar(工具欄)、QStatusBar(狀態欄)以及QDockWidget(懸浮窗體),佈局有一個可由任何種類小窗口所佔據的中心區域。

QMainWindow的模態、非模態和 QWidget一樣可以通過 setWindowModality() 來設置。

QDialog

QDialog類是對話框窗口的基類

對話框窗口是一個頂級窗體,主要用於短期任務以及和用戶進行簡要通訊。QDialog可以是模態的也可以是非模態的。QDialog支持擴展性並且可以提供返回值。它們可以有默認按鈕。

查看幫助文檔我們發現在QDialog中除了繼承QWidget的 show() 方法外,還多了兩個方法來顯示窗口,分別是 open() 和 exec() 方法。

  1. open()
    ![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200330214749800.png
    可以看到使用 open() 方法顯示出的對話框爲窗口級模態對話框,並且立即返回,這樣 open() 方法後的代碼將會繼續執行

示例:

void showWindow()
{
    QWidget* pWindow = new QWidget();

    QWidget* childWindow = new QWidget(pWindow);
    childWindow->setWindowModality(Qt::WindowModal);	// 窗口級模態對話框
    childWindow->show();

    // 上面三行代碼相當於下面兩行代碼
    //QDialog* childDialog = new QDialog(pWindow);
    //childDialog->open();
    
    // 這裏不會阻塞,這行代碼會運行
    qDebug() << "這是一個半模態窗口";
}
  1. exec()
    在這裏插入圖片描述
    可以看到使用 exec() 方法顯示出的對話框爲應用程序級模態對話框,同時會阻塞之前窗口的響應直到用戶關閉這個對話框,並且返回DialogCode(包括Accepted和Rejected兩個值)結果

示例1:

void showModalWindow()
{
    QWidget* pWindow = new QWidget();

    QWidget* childWindow = new QWidget(pWindow);
    childWindow->setWindowModality(Qt::ApplicationModal);	// 應用程序級模態對話框
    childWindow->show();

    // 注意這裏上面的三行代碼不等於下面兩行代碼
    // 上面調用完 show() 方法後立即返回了,並不知道用戶選擇了Accepted還是Rejected
    // 而 exec() 會阻塞後面代碼的執行,直到對話框關閉,返回結果
    //QDialog* childDialog = new QDialog(pWindow);
    //childDialog->exec();
}

示例2:

void showModalWindow()
{
    QWidget* pWindow = new QWidget();

    QDialog* childDialog = new QDialog(pWindow);
    int resutl = childDialog ->exec();
    if (resutl == QDialog::Accepted)
    {
        qDebug() << "You Choose Ok";
    }
    else
    {
        qDebug() << "You Choose Cancel";
    }

    // 在關閉對話框之後,下面的代碼纔可以執行;
    qDebug() << "這纔是一個模態窗口";
}

QWidget、QMainWindow和QDialog的使用原則

  • 如果需要嵌入到其他窗體中,則基於QWidget創建。
  • 如果是頂級對話框,則基於QDialog創建。
  • 如果是主窗體,則基於QMainWindow創建。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章