• 【QT】点击按钮弹出对话框的注意事项


    stack区创建对话框对象

    模态对话框,不可以对其他窗口进行操作。 模态窗口用dlg.exec()显示窗口。


    问题代码1:

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        //点击新建按钮,弹出一个对话框
        connect(ui->actionNew, &QAction::triggered, [this](){
            // 阻塞态对话框,只能有一个
            QDialog dlg(this);			// 在stack区创建 dlg
            dlg.resize(200,100);	
            
            //dlg.exec();					// 让窗口对象卡住,点击关闭,关闭窗口。
    
            qDebug() << "模态对话框弹出了";
        });
            
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    对象dlg,在stack区被创建。dlg 的生命周期在Lambda表达式内,当箭头函数结束时,会自动销毁 stack 区内存,窗口一闪即逝


    正确写法,设置exec()函数:

        connect(ui->actionNew, &QAction::triggered, [this](){
            // 阻塞态对话框,只能有一个
            QDialog dlg(this);			// 在stack区创建 dlg
            dlg.resize(200,100);		 
            dlg.exec();					// 让窗口对象卡住,点击关闭,关闭窗口。
    
            qDebug() << "模态对话框弹出了";
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    dlg.exec()相当于 while(1),让窗口对象持续存在。当手动叉掉对话框时,箭头函数就会结束,并自动销毁 stack 区内存,不会出现内存泄漏。


    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传



    在堆区创建对话框对象

    非模态对话框,可以对其他窗口进行操作。非模态窗口用dlg->show()显示窗口。


    问题代码2:

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        //点击新建按钮,弹出一个对话框
        connect(ui->actionNew, &QAction::triggered, [this](){
            // 非模态对话框
            QDialog *dlg2 = new QDialog(this);
            dlg2->resize(200,100);
            dlg2->show();
            
            qDebug() << "非模态对话框弹出了";
        });
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    程序不会报错,运行结果和上图差不多。但是已经出现了内存泄漏。

    dlg2虽然在stack区创建,但是它指向的对象 new QDialog() 在堆区创建,当箭头函数结束时,堆区内存不会被自动释放。因此对话框会持续保留,不需要exec()函数卡住程序

    又因为dlg2非模态对话框,可以无限在堆区开辟空间,每次开辟只会改变dig2的指向,堆区的内存不会被销毁。理论上讲,只要用户无限点击几天时间,就会占用大量堆区的内存。只要主程序没有结束,对象树的自动析构就不会起作用,即使叉掉对话框,也不会释放。这是一个重大的安全隐患。


    正确写法,设置Qt::WA_DeleteOnClose属性: 使Qt在小部件接受关闭事件时删除该小部件。

        connect(ui->actionNew, &QAction::triggered, [this](){
            // 非模态对话框
            QDialog *dlg2 = new QDialog(this);
            dlg2->resize(200,100);
            dlg2->show();
            
            dlg2->setAttribute(Qt::WA_DeleteOnClose);  //55号属性
            
            qDebug() << "非模态对话框弹出了";
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    未设置该属性时,你去关闭窗口,窗口资源不会立即释放,窗口只是"隐藏"了。当调用析构函数时,窗口资源才会真正释放。设置该属性后,我们关闭窗口,窗口资源会立即释放。



    完整的示例代码

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
    
        //点击新建按钮,弹出一个对话框
        connect(ui->actionNew, &QAction::triggered, [this](){
            // 阻塞态对话框
            QDialog dlg(this);
            dlg.resize(200,100);
            dlg.exec();
    
            qDebug() << "模态对话框弹出了";
    
    
    
            // 非模态对话框
            QDialog *dlg2 = new QDialog(this);
            dlg2->resize(200,100);
            dlg2->show();
            dlg2->setAttribute(Qt::WA_DeleteOnClose);  //55号属性
            qDebug() << "非模态对话框弹出了";
        });
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27




    参考连接:

    setAttribute(Qt::WA_DeleteOnClose) 导致程序崩溃问题

  • 相关阅读:
    Cocoa-window
    电脑数据丢失如何恢复呢?
    第四章 测试用例编
    【Python计算机视觉】Python全栈体系(二十六)
    初学者入门的可视化超级色彩公式
    你必须要知道的关于直线导轨的五个小知识点
    Oxidized-Docke配置
    Java中数组的实际经典案例
    springboot启动后和停止前执行方法
    华为云云耀云服务器L实例评测|部署spring项目端口开放问题的解决 & 服务器项目环境搭建MySQL,Redis,Minio...指南
  • 原文地址:https://blog.csdn.net/zsyyugong/article/details/134063985