【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() << "模态对话框弹出了";
    });
        
}

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


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

    connect(ui->actionNew, &QAction::triggered, [this](){
        // 阻塞态对话框,只能有一个
        QDialog dlg(this);			// 在stack区创建 dlg
        dlg.resize(200,100);		 
        dlg.exec();					// 让窗口对象卡住,点击关闭,关闭窗口。

        qDebug() << "模态对话框弹出了";
    });

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() << "非模态对话框弹出了";
    });

}

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

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() << "非模态对话框弹出了";
    });

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



完整的示例代码

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() << "非模态对话框弹出了";
    });
}




参考连接:

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值