一 引言:
熟悉win32(MFC)的小伙伴们会知道, 对话框分为模态对话框和非模态对话框,他们的明显差异是: 模态对话框在弹出后,会阻塞同一应用程序中其它窗体的输入,即无法获取鼠标和键盘等响应。模态对话框很常见,比如记事本的“打开文件”功能。当“打开文件”对话框弹出后,我们无法对此外的窗口进行操作的。而非模态对话框在弹出后,其他窗体依旧可以获取响应。例如记事本的“查找”对话框,我们可以在查找的同时,继续对记事本的内容进行编辑等操作。
二 Qt的对话框介绍:
模态和非模态不是Win32所独有的,在各种不同的平台下都存在。又有叫法是称为模式对话框,无模式对话框等。Qt也引入了此概念,其基本特点与之前描述类似,即:模态对话框就是在其没有被关闭之前,用户不能与同一个应用程序的其他窗口进行交互,直到该对话框关闭。对于非模态对话框,当被打开时,用户既可选择和该对话框进行交互,也可以选择同应用程序的其他窗口交互。
三 Qt中模态与非模态的实现:
在Qt中,显示非模态对话框一般通过QDialog的成员函数show()实现,其默认显示非模态对话框,但并非一定如此,后面介绍。显示模态对话框主要有两种方式,其定义略有差异,一是通过exec()成员函数实现,叫做应用程序级别的模态对话框,其肯定显示为模态对话框;二是通过open()成员函数实现,叫做窗口级别的模态对话框,其默认显示为模态对话框,但并非一定如此,同样后面再介绍,下面先看代码:
#include "widget.h"
#include "ui_widget.h"
#include <QDialog>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//! 信号槽
connect(ui->pushButton_Test, &QPushButton::clicked, this, &Widget::testSlot);
}
Widget::~Widget()
{
delete ui;
}
void Widget::testSlot()
{
//! show()
QDialog *dlg = new QDialog(this);
dlg->show();
}
上面实现用show()函数实现非模态对话框的显示,代码比较简单,单击按钮弹出对话框,不做过多解释。要实现非模态对话框最要有两种形式,代码如下:
void Widget::testSlot()
{
//! 使用exec()实现模态对话框
QDialog dlg;
dlg.exec();
}
void Widget::testSlot()
{
//! 使用open()实现模态对话框
QDialog *dlg = new QDialog;
dlg->open();
}
首先看Qt中定义的3种模式状态:Qt::NonModal、Qt::ApplicationModal和Qt::WindowModal,它们分别代表非模态、应用程序级别的模态和窗口级别的模态。这就引出了上述三个函数的差异。
下面来具体讲述三个函数的特点及差异:
1.show()函数,默认创建非模态对话框,即默认设置状态为Qt::NonModal。另外上面还说过,并非一定是非模态对话框,意思是:可以通过setModal(true)实现模态对话框的创建。此时状态应为Qt::ApplicationModal。另外其在被调用后直接返回,为非阻塞形式。
2.exec()函数,设置状态为Qt::ApplicationModel,其一定创建模态对话框,对setModal()函数的设置忽略之。其特点是阻塞同一进程的其他窗体,并且被调用后不会直接返回,一直等到关闭对话框。
3.open()函数,其是在Qt4.5中新加入的,默认设置状态为Qt::WindowModal。其同样可以通过setModal(false)实现非模态对话框的创建。其被调用后直接返回。
exec()和open()函数都可以完成模态对话框的创建,他们的差异在哪呢?忽略open()可以创建非模态的特点,针对模态对话框的创建,有如下差异:
1.exec()不管是否设置父类,其必定会阻塞同一进程中的其他窗体;而open()函数只有在设置其父类(窗体类)后,才会对其父类所在的进程进行阻塞,即不将this传入其不会阻塞本进程的其他窗体。
2.exec()会阻塞等待,直到对话框关闭才返回;而open()调用后直接返回。
四 对话框的资源回收
由于show()函数和open()函数在调用后直接返回,若在栈上分配空间会导致资源的自动回收(当然可以声明为类成员变量,不考虑此情况),所以最好在堆上分配,但问题是函数返回后由谁负责回收呢,一般有两种方法:
1.将this作为父类,在其父类析构时会自动销毁;
2.进行一下设置:setAttribute (Qt::WA_DeleteOnClose),其作用在对话框关闭后自动销毁内存占用。
针对exec()函数的特点可以为对话框在栈上分配内存,在关闭对话框后会函数返回后会自动销毁;而针对在堆上分配的内存,需要通过一下设置进行回收:调用deleteLater()函数,其会在消息循环结束后自动调用进行资源回收。
另外再说一个对话框的一个特点,模态非模态一样。若在创建时未设置其父类,那么在显示时会在任务栏出现对话框的标识,如下图:
关于Qt对话框的讲述先到此为止了,本文只是简单介绍,还有很多相关内容未展开(本人也不熟悉~),请自行查阅资料。