【Qt】Qt窗口(五)QDialog对话框的使用,点击按钮弹出新的对话框,自定义对话框界面,模态对话框model

小编个人主页详情<---请点击
小编个人gitee代码仓库<---请点击
Qt系列专栏<---请点击
倘若命中无此运,孤身亦可登昆仑,送给屏幕面前的读者朋友们和小编自己!


目录


前言

【Qt】Qt窗口(四)QStatusBar状态栏,QDockWidget子窗口/浮动窗口的使用------书接上文 详情请点击<------

本文由小编为大家介绍------【Qt】Qt窗口(五)QDialog对话框的使用,点击按钮弹出新的对话框,自定义对话框界面,模态对话框model


一、QDialog

QDialog的介绍

  1. 相信不少读者友友都玩过王者荣耀,那么我们登录进入王者荣耀的时候,会弹出很多的窗口,其实这些窗口的本质就是对话框,对话框往往用于和用户进行短平快的操作,那么毫无疑问,这些对话框对于用户使用客户端程序来讲是非常重要的,如果王者荣耀不弹出这些对话框,那么用户就无法快速的得知出了什么活动,出了什么皮肤等等,所以这些对话框在客户端程序中的存在是非常必要的
  2. 在Qt中使用QDialog这个类表示对话框,小编,好像我们在之前创建项目的时候见过QDialog这个类 关于QDialog这个类,在第四点使用Qt Creator创建项目中的第10点进行讲解,详情请点击<------,也就是我们创建项目的时候可以选择三个基类进行继承,这三个基类分别是QWidget,QMainWindow,QDialog
  3. 那么也就意味着我们可以选择QDialog这个类作为基类然后创建dialog派生类这个项目,所以接下来我们创建一个项目名为QDialog,基类为QDialog,派生类为Dialog的项目

运行结果如下

  1. 所以如上,不废话,我们直接运行程序,看一下这个对话框QDialog长什么样子
  2. 诶,这乍一看,好像这个基于对话框QDialog作为基类创建出来的窗口和我们之前通过QWidget作为基类创建出来的窗口长得差不多,十分的类似
  3. 但是仔细一看,对话框QDialog右上角没有QWidget窗口的最小化➖️和最大化 口 这两个按键取而代之的是一个问号 ? 表示提示信息
  1. 那么为什么以QDialog和QWidget作为基类创建出来的窗口十分相似呢?所以如上,我们点击ui文件,进入Qt Designer中寻找答案,此时右下角,我们看到了QDialog的继承体系,原来QDialog是继承自QWidget,所以QDialog具有QWidget的全部属性和方法等,所以QDialog和QWidget作为基类创建出来的窗口十分相似,并且QDialog还有自己的一些属性,那么关于QDialog自己的属性小编会在后面合适的时机进行讲解
  2. 同样的由于对话框在GUI图形化程序中使用的场景较多,尤其是在与用户交互上必不可少,所以Qt同样也基于QDialog作为基类,然后实现了很多对话框派生类,这些对话框派生类也就是Qt内置的现成的对话框,可以供我们直接进行使用,Qt内置的对话框如下
    (1)QFileDialog,文件对话框,显示一个对话框,用于选择一个文件
    (2)QColorDialog,颜色对话框,显示一个对话框,用于选择一种颜色
    (3)QFontDialog,字体对话框,显示一个对话框,用于选择一种字体
    (4)QInputDialog,输入对话框,显示一个对话框,用于让用户输入字符串
    (5)QMessageBox,消息对话框,显示一个对话框,用于显示一串字符串,同样的类比一下,当我们登录进入王者荣耀的时候弹出的就应该是消息对话框,只不过这些对话框上显示的是图片,并且支持了点击跳转的功能
  3. Qt内置提供的对话框可以在一定程度上满足我们我们的使用需求,但是在实际开发中根据场景的不同我们需要自定义对话框,即此时Qt内置提供的对话框就不能满足我们的需求了,我们需要针对这个对话框作为基类进行自定义实现派生类
  4. 那么在实际开发中,项目创建的是主窗口,由于主窗口一般不是对话框,所以我们在创建项目的时候继承并不是让项目继承自对话框QDialog,而是让项目继承自QMainWindow这个主窗口,然后在代码中,创建出额外的类,让这个额外的类继承自QDIalog,此时就可以实现出针对对话框自定义的效果,然后将这些自定义的对话框放置到程序主窗口中即可

点击按钮弹出新的对话框

  1. 通过上面的学习,我们对于对话框已经有了一个最基本的认识了,下面就基于QDialog实现一下在主窗口中,通过点击按钮,弹出一个新的对话框,所以接下来我们创建一个项目名为QDialog_2,基类为QMainWindow,派生类为MainWindow的项目,接下来我们点击ui文件,进入Qt Designer
  2. 所以此时我们拖拽左侧红框内的按钮控件,设置按钮显示的文本为弹出一个对话框,然后调整成上图界面即可,objectName保持不变,接下来我们右击,然后点击转到槽,接下来我们选择clicked信号,让Qt帮我们生成对应槽函数的声明和定义
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QDialog* dialog = new QDialog(this);

    dialog->show();
}
  1. 所以此时我们在点击信号对应的槽函数中创建QDialog对象,并且传参主窗口MainWindow对应的this指针,指定对话框QDialog的父元素为主窗口MainWindow,但是别忘了此时虽然对话框创建了,但是对话框还没有显示到界面上,所以我们调用show方法显示对话框QDialog

运行结果如下

  1. 此时我们点击按钮,那么此时确实弹出了一个对话框,可是这个对话框太小了,我们想将对话框变大一点
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QDialog* dialog = new QDialog(this);

    dialog->resize(400, 300);

    dialog->show();
}
  1. 而调整窗口大小我们可以使用QWidget中的resize接口,嘶,QWidget中的resize接口,那么QDialog可以使用吗?可以,因为QDialog继承自QWidget,即QDialog是QWidget的派生类,所以QWidget中的各种属性和方法,在QDialog中都可以进行使用

运行结果如下

  1. 所以此时点击按钮,弹出的对话框的大小就大一点了
  2. 并且我们还可以点击对话框右上角的❌️关闭按钮,此时对话框就关闭了
  1. 可是问题来了,我们此时点击对话框右上角的❌️关闭按钮真的就关闭了吗?是的,在我们表面上来看,对话框确实是关闭了,但是要知道这个对话框当初被创建出来的时候是指定了父元素为主窗口MainWindow挂接到对象树上了,也就是说对话框此时的生命周期随主窗口MainWindow,也就是说由于主窗口MainWindow没有关闭释放销毁,所以对话框仍然存在,问题此时就来了
  2. QDialog对话框不同于界面上的其它控件,对于我们每次按下按钮,弹出一个QDialog对话框的时候,new创建一个新的QDialog对话框对象,指定父元素为主窗口MainWindow挂接到对象树上,接下来进行显示,也就是每次按下按钮都会产生一个QDialog对话框对象,即使用户点击了关闭按钮,但是由于QDialog对话框对象被挂接到了对象树上,生命周期随主窗口
  3. 所以今天我是一个很无聊的用户,我点击了按钮10次,100次,1000次,10000次,100000次乃至更多,即在这样一个程序运行的过程中,用户可以无数次点击这个按钮,进而就会产生出无数的QDialog对话框对象了,用户点击了关闭QDialog对话框,对话框从表面上看是关闭了,但是实际上这些QDialog对话框对象都被挂接到了对象树中,也就是还占用着内存,此时无数的QDialog对话框没有被释放就会占用着大量的内存进而就造成了内存泄露
  4. 虽然当主窗口销毁的时候,这些无数的QDialog对话框对象就会随之销毁,如果主窗口没有关闭,也就是说在主窗口关闭之前产生了无数这样的QDialog对话框对象,造成了内存泄露,随着QDialog对话框对象的越来越多,程序越来越卡,随着QDialog对话框对象的数量到了某个限度,啪的一下,内存扛不住,程序就崩溃了,同样的在QDialog对话框对象本身就很大,以及在嵌入式设备系统内存本身空间就很少,这种现象会更加严重
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QDialog* dialog = new QDialog(this);

    dialog->resize(400, 300);

    dialog->show();


    delete dialog;
}
  1. 那么如何解决呢?本身不就是由于QDialog对话框对象被创建出来之后没有及时delete释放造成的嘛,所以此时我在QDialog对话框对象显示之后,调用delete释放析构QDialog对话框对象即可

运行结果如下

  1. 所以此时很快的,小编点击按钮,触发按钮的clicked信号,进而就会去执行clicked信号关联的槽函数,所以此时就会创建QDialog对话框对象,然后显示QDialog对话框,接下来一瞬间我们又调用delete将QDialog对话框对象析构释放了
  2. 确实此时用户无论点击多少次按钮,弹出多少次对话框都不会造成内存泄露了,但是有一个最要命的问题,我们创建出对话框是为了什么?
  3. 是为了和用户进行交互,这个对话框此时由于我们的设定,一瞬间对话框就没了,一闪而过,此时就无法和用户进行交互了,所以我们该如何做呢?
  1. 正确的做法应该是,当用户点击QDialog对话框右上角的关闭按钮的时候,再来触发这里的delete析构QDialog对话框对象的操作,所以此时我们给QDialog对话框右上角的关闭按钮设置槽函数,然后再在槽函数中实现delete析构QDialog对话框对象的操作即可
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QDialog* dialog = new QDialog(this);

    dialog->resize(400, 300);

    dialog->show();


//    delete dialog;
    
    dialog->setAttribute(Qt::WA_DeleteOnClose);
}
  1. 其实Qt很贴心,为了让我们写代码方便,这样的方案Qt已经帮我们写好了,即Qt已经内置好了,我们只需要使用setAttribute给QDialog对话框对象设置Qt::WA_DeleteOnClose这样的属性,那么此时Qt就会在QDialog对话框对象的右上角❌️关闭按钮被点击的时候自动进行delete析构释放QDialog对话框对象

运行结果如下

  1. 此时用户点击按钮,就会弹出一个对话框,当用户点击对话框右上角的关闭按钮的时候,QDialog对话框对象就会自动进行delete析构释放,所以此时就不会出现内存泄露问题了
  2. 真的不会嘛,如果我用户就不点击对话框右上角的关闭按钮呢?而是用户不断的点击按钮,弹出对话框,由于用户不点击对话框右上角的关闭按钮
  3. 用户就这样点击了一亿次按钮,弹出对话框,并且用户不点击对话框右上角的关闭按钮,此时程序崩溃了,我们如何理解呢?
  4. 用户是魔丸来的呗,在程序设计上我们已经设计的很好了,不需要任何优化了,就比如电脑的浏览器,是否开发者会不让我们不断的打开新的页面嘛?不会
  5. 不会,而是在用户不断打开新的页面,与此同时用户不关闭旧的页面,此时浏览器会越来越卡,我们将用户打开界面的数量这部分权利留给用户,可以不断的打开页面,但是会越来越卡,直至卡死,浏览器程序崩溃,所以崩溃,崩溃了之后用户一重启浏览器就没事了
  6. 注意观察,此时上面对话框的标题是QDialog_2,所以我们期望修改一些对话框的标题
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QDialog* dialog = new QDialog(this);

    dialog->setWindowTitle("对话框的标题");
    
    dialog->resize(400, 300);

    dialog->show();


//    delete dialog;

    dialog->setAttribute(Qt::WA_DeleteOnClose);
}
  1. QWidget中可以使用setWindowTitle设置窗口的标题,由于QDialog是QWidget的派生类,所以QDialog可以使用QWidget的所有属性和方法,所以此时我们可以使用setWindowTitle将QDialog对话框的标题进行设置 关于窗口标题,在第二点QWidget的windowTitle属性中进行的讲解,详情请点击<------

运行结果如下

  1. 所以此时对话框的标题就显示为我们设置好的标题了,无误
  2. 但是上述对话框仅仅是对话框,里面一个控件都没有,所以我们该如何向对话框中添加控件呢?

自定义对话框界面

纯代码的方式实现
  1. 对于一个对话框来讲,我们往往需要向对话框中添加一些控件,也就是需要实现自定义对话框,此时问题就来了,我们该如何实现自定义对话框呢?那么此时我们就需要使用额外的类去继承自QDialog类,有纯代码的方式,也有图形化的方式,下面小编先来介绍一下通过纯代码的方式实现,所以接下来我们创建一个项目名为QDialog_3,基类为QMainWindow,派生类为MainWindow的项目,接下来我们点击ui文件,进入Qt Designer
  2. 所以此时我们拖拽左侧红框内的按钮控件,修改显示的文字为弹出一个对话框,然后调整成上图界面即可,objectName保持不变,接下来我们右击按钮,然后点击转到槽,接下来我们选择clicked信号,让Qt帮我们生成对应槽函数的声明和定义
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialog.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    Dialog* dialog = new Dialog(this);
    dialog->resize(400, 300);
    dialog->setAttribute(Qt::WA_DeleteOnClose);

    dialog->show();

}
  1. 那么在按钮的槽函数中,我们创建一个对话框,指定父元素为MainWindow主窗口,然后使用resize调整对话框的带下,接下来使用setAttribute传入Qt::WA_DeleteOnClose让Qt帮我们在用户点击对话框右上角的关闭按钮的时候就将对话框释放掉,最后使用show将对话框显示出来即可
  2. 所以此时我们就需要使用额外的类继承自QDialog了,所以此时我们鼠标点击左上角的文件,选择新建文件或项目,接下来在左侧的文件和类中选择C++,然后继续选择C++ Class,将生成的类的名称命名为Dialog,然后填充继承的类为QDialog即可,接下来勾选Add Q_OBJECT主要是为了使用信号槽机制,接下来一路下一步即可
  3. 此时就可以让Qt帮我们生成继承自QDialog的派生类Dialog,如上关于这个类的声明相关的.h头文件就有了,关于这个类的.cpp源文件就有了
cpp 复制代码
#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

class Dialog : public QDialog
{
    Q_OBJECT
public:
    Dialog(QWidget* parent);
};

#endif // DIALOG_H
  1. 那么在.h头文件中,我们加上基类QDialog的头文件#include <QDialog>,然后再Dialog的构造函数的形参中加上QWidget* parent,主要是为了使用对象树机制,将父元素传参给基类QDialog,然后使用基类的对象树机制将派生类一并挂接到对象树中指定的的父元素下
cpp 复制代码
#include "dialog.h"
#include <QLabel>
#include <QPushButton>


Dialog::Dialog(QWidget* parent)
    : QDialog(parent)
{
    QLabel* label = new QLabel("这是一个QLabel", this);
    QPushButton* button = new QPushButton("关闭", this);

}
  1. 所以此时我们在自定义对话框Dialog类的.cpp文件中对于构造函数的参数设置为QWidget* parent,所以此时在初始化列表中传入父元素parent调用基类QDialog的构造函数,将派生类Dialog设置进对象树中父元素parent下即可
  2. 在Dialog的构造函数中,我们创建一个QLabel标签,设置文本,指定父元素为我们当前的自定义的对话框Dialog,所以此时QLabel标签就会显示到自定义对话框Dialog的界面中了,同样的,我们创建一个按钮,设置文本,指定父元素为我们当前的自定义的对话框Dialog,所以此时按钮就会显示到自定义对话框Dialog的界面中了
  3. 讲解到这里,那么细心的读者友友会发现,这里向自定义对话框Dialog的窗口界面中添加控件的方式和当初我们向Widget,MainWindow窗口界面内添加控件的方式是一致的,是的,就是一致的,这同样也降低了我们的学习成本,触类旁通,更好学习

运行结果如下

  1. 此时我们点击MainWindow主窗口上的按钮弹出一个对话框,此时对话框显示的QLabel,按钮这两个控件重合在一起了,不符合我们的期望
  2. 所以小编可以向自定义对话框中引入垂直布局管理器
cpp 复制代码
#include "dialog.h"
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>

Dialog::Dialog(QWidget* parent)
    : QDialog(parent)
{
    QVBoxLayout* layout = new QVBoxLayout();
    this->setLayout(layout);

    QLabel* label = new QLabel("这是一个QLabel", this);
    QPushButton* button = new QPushButton("关闭", this);

    layout->addWidget(label);
    layout->addWidget(button);



}
  1. 所以此时我们使用垂直布局管理器 关于垂直布局管理器,在第一点QVBoxLayout中进行讲解,详情请点击<------,先创建垂直布局管理器对象,使用setLayout将垂直布局管理器设置进this指针对应的Dialog窗口中,接下来使用addWidget将QLabel和按钮添加到垂直布局管理器中即可

运行结果如下

  1. 此时我们点击MainWindow主窗口上的按钮弹出一个对话框,此时对话框显示的QLabel,按钮这两个控件就不重合在一起了,而是符合我们的预期,呈现行方向的分布,也就是垂直分布
  2. 但是此时小编点击按钮没有反应,按钮上显示的文字是关闭,所以我们需要借助信号槽机制实现按钮的关闭
cpp 复制代码
#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>

class Dialog : public QDialog
{
    Q_OBJECT
public:
    Dialog(QWidget* parent);

public slots:
    void handle();

};

#endif // DIALOG_H
cpp 复制代码
#include "dialog.h"
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>

Dialog::Dialog(QWidget* parent)
    : QDialog(parent)
{
    QVBoxLayout* layout = new QVBoxLayout();
    this->setLayout(layout);

    QLabel* label = new QLabel("这是一个QLabel", this);
    QPushButton* button = new QPushButton("关闭", this);

    layout->addWidget(label);
    layout->addWidget(button);

    connect(button, &QPushButton::clicked, this, &Dialog::handle);

}

void Dialog::handle()
{
    this->close();
}
  1. 所以此时我们现在Dialog的.h头文件中声明一个槽函数handle,接下来使用connect连接按钮发出的clicked信号和自定义槽函数handle即可,那么在自定义槽函数handle中,我们使用Dialog对话框对应的this指针调用close,此时就可以实现关闭对话框的功能
    (1)关于信号槽中connect的讲解,详情请点击<------
    (2)关于信号槽中自定义槽函数的讲解,详情请点击<------

运行结果如下

  1. 此时我们点击MainWindow主窗口上的按钮弹出一个对话框,此时对话框显示的QLabel,按钮这两个控件
  2. 接下来我们点击对话框中的关闭按钮,此时对话框就关闭了,没有问题
  3. 那么我们再来深究一下这里的过程,首先是我们点击对话框的关闭按钮,触发关闭按钮的clicked信号,进而就会去执行关联的槽函数handle,此时就会通过this指针调用close,进而对话框就关闭了
图形化的方式实现
  1. 接下来小编讲解一下通过图形化的方式实现自定义对话框,同样的通过图形化的方式也是要继承自QDialog,关键操作是要创建出一个新的ui文件来,所以接下来我们创建一个项目名为QDialog_4,基类为QMainWindow,派生类为MainWindow的项目
  2. 那么我们鼠标点击左上角的文件,选择新建文件或项目,接下来上图左侧选择Qt,中央选择Qt设计师类,在上图右侧的说明中讲解到会生成一个Qt设计师窗体文件,那么这个Qt设计师窗体文件也就是我们通常说的ui文件,同样也会生成相关的类,这里的类我们后面会选择继承自QDialog的Dialog,也就说不仅仅会自动生成ui文件,同样也会生成Dialog的.h头文件和.cpp源文件
  3. 接下来我们上图左侧我们选择Dialog without Buttons,此时在上图的右侧就会选择继承自QDialog的类Dialog了,接下来我们一路下一步即可
  4. 此时就自动生成了Dialog类对应的.h头文件和.cpp源文件,以及对应自定义对话框的一个ui文件了
  5. 此时我们点击ui文件,这里的界面就和当初我们使用的Widget对应的ui文件的界面相同
  6. 所以此时我们拖拽左侧红框内的控件,然后调整成上图界面即可,objectName保持不变,接下来我们右击关闭按钮,然后点击转到槽,接下来我们选择clicked信号,让Qt帮我们生成对应槽函数的声明和定义
cpp 复制代码
#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::on_pushButton_clicked()
{
    this->close();
}
  1. 所以此时我们就使用Dialog对话框对应的this指针调用close,此时就可以实现关闭对话框的功能了
  2. 接下来我们点击MainWindow的ui文件,拖拽左侧红框内的按钮控件,然后调整成上图界面即可,objectName保持不变,接下来我们右击按钮,然后点击转到槽,接下来我们选择clicked信号,让Qt帮我们生成对应槽函数的声明和定义
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialog.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    Dialog* dialog = new Dialog(this);

    dialog->resize(400, 300);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->setWindowTitle("这是一个对话框");

    dialog->show();
}
  1. 那么在MainWindow的.cpp源文件中我们需要使用Dialog类,所以就需要包含Dialog类对应的头文件#include "dialog.h",接下来在按钮的clicked点击信号对应的槽函数中,此时我们先创建一个Dialog自定义对话框对象,挂接到对象树上指定父元素为this指针对应的MainWindow主窗口,接下来使用resize设置对话框大小
  2. 使用setAttribute给Dialog自定义对话框对象设置Qt::WA_DeleteOnClose这样的属性,那么此时Qt就会在Dialog自定义对话框对象的右上角❌️关闭按钮被点击的时候自动进行delete析构释放Dialog自定义对话框对象,接下来使用setWindowTitle设置自定义对话框Dialog的窗口标题,最后我们调用show将自定义对话框Dialog显示出来即可

运行结果如下

  1. 此时我们点击MainWindow主窗口上的按钮弹出一个对话框,此时对话框显示的QLabel,按钮这两个控件
  2. 接下来我们点击对话框中的关闭按钮,此时对话框就关闭了,没有问题
  3. 那么我们再来深究一下这里的过程,首先是我们点击对话框的关闭按钮,触发关闭按钮的clicked信号,进而就会去执行关联的槽函数handle,此时就会通过this指针调用close,进而对话框就关闭了
  1. 通过上面的讲解,我们了解了通过纯代码的方式和通过图形化的方式都可以自定义对话框界面,但是在实际开发中我们更推荐使用图形化的方式自定义对话框界面,因为通过纯代码的方式对于对话框内的各个控件的位置需要我们手动通过像素坐标位置以及尺寸进行设置,需要凭借一定的想象力,较为抽象
  2. 但是通过图形化的方式,我们可以直接拖拽控件到对话框界面上,并且控件的位置和尺寸也好调整,较为容易,但是有的读者友友可能会想,纯代码的方式我们不是可以设置布局管理器嘛,布局管理器自动调节控件的位置和尺寸不就好了,但是有的场景中我们并不需要让界面内的控件跟随界面自动调整控件的位置和尺寸,即界面的大小是固定的
  3. 并且有时候我们也需要将某个控件放到界面的特定位置,此时布局管理器不能满足我们的需求,即使我们引入空白,但是也不容易进行控制,同样的,别忘了即使是图形化的方式也可以使用图形化的方式引入布局管理器,所以我们实际场景中更推荐更推荐使用图形化的方式自定义对话框界面

模态对话框model

  1. 在QDialog中model是一个bool类型的属性,如果model为true表示模态,如果model为false表示非模态
    (1)模态,弹出对话框的时候,此时用户无法操作父窗口,必须完成对话框内部的操作,关闭对话框之后才可以操作父窗口,模态对话框一般用于特别关键的场合,要求用户必须做出决策
    (2)非模态,弹出对话框的时候,用户可以操作父窗口,一般用户一些不是特别关键的场景
  2. 接下来,我们继续运行上面图形化的方式实现自定义对话框的程序,此时我们点击MainWindow主窗口上的弹出一个对话框,此时弹出了一个对话框,此时对话框Dialog的父窗口是MainWindow,所以此时我们拖拽对话框Dialog的父窗口MainWindow,然后点击MainWindow主窗口上的弹出一个对话框,此时弹出了一个对话框,重复此过程
  3. 那么对于弹出了一个对话框Dialog来讲,此时没有关闭对话框Dialog的时候,就可以操作Dialog的父窗口,即可以拖拽,可以点击父窗口,所以也就意味着前面写的几个程序都是非模态对话框,也就代表model为false,表示对话框为非模态对话框
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "dialog.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    Dialog* dialog = new Dialog(this);

    dialog->resize(400, 300);
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    dialog->setWindowTitle("这是一个对话框");

//    dialog->show();
    dialog->exec();
}
  1. 所以呢?我们该如何实现模态对话框呢?其实也很简单,把展示自定义对话框的show方法换成exec方法即可

运行结果如下

  1. 此时我们点击MainWindow主窗口上的弹出一个对话框,此时弹出了一个对话框,此时对话框Dialog的父窗口是MainWindow,所以此时我们拖拽或者关闭对话框Dialog的父窗口MainWindow,无法拖拽或者关闭,即此时我们无法操作对话框Dialog的父窗口MainWindow,那么关闭或者点击对话框右上角的❌️之后才可以操作对话框Dialog的父窗口MainWindow,所以此时就实现了模态对话框

  2. 其实关于模态对话框的使用,这里小编就不得不提到2010年左右互联网发生的一件大事,那就是3Q大战,这里的3是指360,Q是指腾讯,两家公司之间发生了争斗,关于3Q大战,详情请点击<------

  3. 在360和腾讯QQ发生斗争的过程中,360使用的手段是推出产品360扣扣保镖,来限制QQ获取用户隐私,腾讯使用的手段是弹出一个对话框,我们做出了一个非常让人痛心的决定,用户想要使用QQ,就需要先卸载360,否则QQ将无法使用,这里的对话框其实使用的就类似于Qt中的模态对话框,只有用户卸载了360之后,才可以操作对话框的父窗口QQ

  4. 360和腾讯QQ闹得不可开交,最后是国家工信部亲自下场调节360和腾讯QQ这两家互联网公司的矛盾,腾讯允许360和腾讯QQ在一台电脑上使用,360下架召回360扣扣保镖这款软件


总结

以上就是今天的博客内容啦,希望对读者朋友们有帮助

水滴石穿,坚持就是胜利,读者朋友们可以点个关注

点赞收藏加关注,找到小编不迷路!

相关推荐
羽翼未丰的啊博1 小时前
Can_Chart上位机
网络·qt·汽车
枫叶丹41 小时前
【HarmonyOS 6.0】CANN Kit 新增支持获取 AI 模型 Dump 维测数据功能详解
开发语言·人工智能·华为·信息可视化·harmonyos
晴夏。1 小时前
c++调用lua的方法
c++·游戏引擎·lua·ue
沐知全栈开发1 小时前
JavaScript Array(数组)
开发语言
Lhan.zzZ9 小时前
笔记_2026.4.28_004
c++·ide·笔记·qt
MATLAB代码顾问9 小时前
5大智能算法优化标准测试函数对比(Python实现)
开发语言·python
wuminyu11 小时前
专家视角看Java字节码加载与存储指令机制
java·linux·c语言·jvm·c++
万粉变现经纪人11 小时前
如何解决 pip install llama-cpp-python 报错 未安装 CMake/Ninja 或 CPU 不支持 AVX 问题
开发语言·python·开源·aigc·pip·ai写作·llama
清风明月一壶酒11 小时前
OpenClaw自动处理Word文档全流程
开发语言·c#·word