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创建。
发布了61 篇原创文章 · 获赞 218 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_34139994/article/details/105192785