欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Qt中的模态、非模态、半模态对话框

程序员文章站 2024-03-15 08:17:47
...


1. 模态对话框(Modal)


模态对话框 是指在同一个应用程序中,阻塞其他可见窗口输入的对话框。一般用于用户输入文件名或用于应用程序的配置选项。可以分为应用模态和窗口模态。

下面是一个模态对话框的显示效果:
Qt中的模态、非模态、半模态对话框对话框的完整代码如下:
头文件:

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)


非模态对话框 是独立于同一应用程序中的其他窗口而运行的对话框。例如,文字处理程序中的查找和替换对话框通常是非模态的,以允许用户与应用程序的主窗口和对话框交互。

下面是非模态对话框的展示效果:
Qt中的模态、非模态、半模态对话框
其中对话框的内容部分与上面的模态相同,调用 部分有所差异:

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. 半模态对话框


我们所说的 半模态 通常是指模态对话框但是代码不会被阻塞。

下面时一个半模态的效果示例:
Qt中的模态、非模态、半模态对话框

调用部分代码如下:

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() 后, 代码继续向下执行,而不是阻塞在此处。