Qt中的模態、非模態、半模態對話框


1. 模態對話框(Modal)


模態對話框 是指在同一個應用程序中,阻塞其他可見窗口輸入的對話框。一般用於用戶輸入文件名或用於應用程序的配置選項。可以分爲應用模態和窗口模態。

下面是一個模態對話框的顯示效果:
模態對話框對話框的完整代碼如下:
頭文件:

class ModalDialog : public QDialog
{
    Q_OBJECT
public:
    ModalDialog(QWidget* parent = nullptr);
    ~ModalDialog();

    void setContentText(const QString& text);

signals:
    void clickedOKButton(void);
    void clickedCannelButton(void);

private:
    QLabel* m_pContentLabel = nullptr;
};

cpp文件

ModalDialog::ModalDialog(QWidget* parent)
    :QDialog(parent)
{
    QVBoxLayout* mainLayout = new QVBoxLayout(this);
    m_pContentLabel = new QLabel();
    m_pContentLabel->setMinimumSize(200, 120);
    m_pContentLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    mainLayout->addWidget(m_pContentLabel);

    // 添加按鈕
    QPushButton* okButton = new QPushButton("確定");
    QPushButton* cannelButton = new QPushButton("取消");
    QHBoxLayout* bottomLayout = new QHBoxLayout();
    bottomLayout->addStretch();
    bottomLayout->addWidget(okButton);
    bottomLayout->addWidget(cannelButton);
    mainLayout->addLayout(bottomLayout);

    // 連接信號
    QObject::connect(okButton, &QPushButton::clicked, this, &ModalDialog::clickedOKButton);
    QObject::connect(cannelButton, &QPushButton::clicked, this, &ModalDialog::clickedCannelButton);
}

ModalDialog::~ModalDialog()
{

}

void ModalDialog::setContentText(const QString& text)
{
    m_pContentLabel->setText(text);
}

整體對話框是繼承自QDialog,界面實現內容比較簡單。

接下來是調用部分:

void MainWindow::onClickedModalButton(void)
{
    ModalDialog dialog(this);
    dialog.setContentText("模態對話框");
    QObject::connect(&dialog, &ModalDialog::clickedOKButton, &dialog, &ModalDialog::accept);
    QObject::connect(&dialog, &ModalDialog::clickedCannelButton, &dialog, &ModalDialog::reject);

    if (dialog.exec() == ModalDialog::Accepted)
        m_pTextEdit->append("Modal: Clicked OK Button");
    else
        m_pTextEdit->append("Modal: Clicked Cannel Button");
    m_pTextEdit->append("Closed Modal Window");
}

點擊 模態對話框 後,調用這部分代碼

  • dialog.exec() , 函數 exec() 會調用顯示一個模態對話框,並使代碼不能向下運行,直到該函數返回。
  • accept() 這是一個槽函數,關聯點擊確定的信號。當點擊按鈕時,函數 exec() 返回 Accepted
  • reject() 這是一個槽函數,關聯點擊取消的信號。當點擊按鈕時,函數 exec() 返回 Rejected
  • 當點擊關閉按鈕是,函數 exec() 也返回 Rejected 。 因此當點擊關閉對話框時,輸出 Modal: Clicked Cannel Button

2. 非模態對話框(Modeless)


非模態對話框 是獨立於同一應用程序中的其他窗口而運行的對話框。例如,文字處理程序中的查找和替換對話框通常是非模態的,以允許用戶與應用程序的主窗口和對話框交互。

下面是非模態對話框的展示效果:
非模態對話框
其中對話框的內容部分與上面的模態相同,調用 部分有所差異:

void MainWindow::onClickedModelessButton(void)
{
    ModalDialog *dialog = new ModalDialog(this);
    QObject::connect(dialog, &ModalDialog::clickedOKButton, \
                     [&]()->void{m_pTextEdit->append("Modeless: Clicked OK Button");});
    QObject::connect(dialog, &ModalDialog::clickedCannelButton, \
                     [&]()->void{m_pTextEdit->append("Modeless: Clicked Cannel Button");});

    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->setContentText("非模態對話框");
    dialog->show();
    m_pTextEdit->append("Created Modeless Window");
}
  • 直接使用函數 show 即可實現非模態對話框,本例子中指定了 parent 否則會出現點擊父窗口子窗口跑到父窗口下面的情況。
  • 這裏使用了 setAttribute(Qt::WA_DeleteOnClose) 表示當關閉是自動釋放內存,否則窗口關閉時不會被自動釋放。
  • 與模態對話框不同,當調用函數 show() 後,代碼不會被阻塞,可以繼續被執行。如果想被阻塞可以使用 QEventLoop 實現。

3. 半模態對話框


我們所說的 半模態 通常是指模態對話框但是代碼不會被阻塞。

下面時一個半模態的效果示例:
半模態對話框

調用部分代碼如下:

void MainWindow::onClickedHalfModalButton(void)
{
    ModalDialog *dialog = new ModalDialog(this);
    QObject::connect(dialog, &ModalDialog::clickedOKButton, \
                     [&]()->void{m_pTextEdit->append("Half Modal: Clicked OK Button");});
    QObject::connect(dialog, &ModalDialog::clickedCannelButton, \
                     [&]()->void{m_pTextEdit->append("Half Modal: Clicked Cannel Button");});
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->setModal(true);
    dialog->setContentText("半模態對話框");
    dialog->show();

    m_pTextEdit->append("Created Half Modal Window");
}
  • 這裏使用函數 setModal(true) 指定窗口爲模態窗口。也可以使用函數 setWindowModality() 實現。
  • 調用函數 show() 後, 代碼繼續向下執行,而不是阻塞在此處。

作者:douzhq
個人主頁:https://www.douzhq.cn
文章同步頁:https://douzhq.cn/qt_modaldialog/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章