【QT】关于Qt::WA_DeleteOnClose的使用问题

2024-03-27 22:18

本文主要是介绍【QT】关于Qt::WA_DeleteOnClose的使用问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天在解决软件bug的过程中,注意到QT关于[slot] bool QWidget::close()有这样一段说明:

If the widget has the Qt::WA_DeleteOnClose flag, the widget is also deleted. A close events is delivered to the widget no matter if the widget is visible or not.

逆向思考,如果我的QWidget或继承于QWidget的派生类没有设置相关的flag:Qt::WA_DeleteOnClose,那么他是不会自动析构的。情况真是如此吗?

测试环境:
macOS Mojave 10.14
Qt Creator 4.41
Qt 5.9.2
Clang 7.0 apple, 64 bits

场景一: 独立widget,没有flag Qt::WA_DeleteOnClose

widget.cpp

#include "widget.h"
#include "ui_widget.h"#include <QDebug>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;qDebug() << "Widget::~Widget()";
}void Widget::on_pushButton_clicked()
{close(); //output: Widget::~Widget()
}

main.cpp

#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

widget.ui:

在这种情况下,不设置flag QT::WA_DeleteOnClose,我们依然可用通过函数链:Widget::on_pushButton_clicked => Widget::close 来触发析构函数。
那么QT关于此flag的说明到底是什么意思呢?接着看下面的场景。

场景二: 自定义的widget作为其他widget的child widget,没有flag Qt::WA_DeleteOnClose

现在widget.ui文件设置成这样:

main.cpp

#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);QWidget parentW;parentW.show();Widget w(&parentW);w.show();setbuf( stdout, NULL );return a.exec();
}

qwidget.cpp

#include "widget.h"
#include "ui_widget.h"#include <QDebug>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);printf( "this: %p\n", this );printf( "ui: %p\n", ui );
}Widget::~Widget()
{delete ui;qDebug() << "Widget::~Widget()";
}void Widget::on_pushButton_clicked()
{qDebug() << testAttribute( Qt::WA_DeleteOnClose );close();
}

一开始显示:

然后我们点击button,button消失。输出:

this: 0x7ffeed17e9e0
ui: 0x7faaacd12c40
false

析构函数没有被调用。

场景三: 自定义的widget作为其他widget的child widget,有flag Qt::WA_DeleteOnClose

在场景二的基础上,Widget的构造函数中加上:

setAttribute( Qt::WA_DeleteOnClose, true );

运行,再点击button,我们得到:

this: 0x7ffee5578a28
ui: 0x7fc99ef14f70
true
Widget::~Widget()
The program has unexpectedly finished.
The process was ended forcefully.

系统报错:error for object 0x7ffee5578a28: pointer being freed was not allocated
也就说,函数链:Widget::on_pushButton_clicked => Widget::close触发了一次析构函数,后面widget的对象又被析构了一次。
注意到我们的Widget对象在main.cpp中是分配到栈内存的,所以在main函数结束后,系统会尝试析构我们的Widget对象。
在qwidget.cpp我们能找到这样的语句:

8442      if (!that.isNull()) {
8443           data.is_closing = 0;
8444           if (q->testAttribute(Qt::WA_DeleteOnClose)) {
8445              q->setAttribute(Qt::WA_DeleteOnClose, false);
8446              q->deleteLater();
8447           }
8448      }
8449      return true;
8450 }

接着,将Widget对象从堆里申请内存,就不会存在多次释放内存的问题了。
main.cpp

Widget *w = new Widget(&parentW);
w->show();

点击红色的button之后:

总结:Qt::WA_DeleteOnClose用于申请堆内存的QWidget对象,并有通过close方法释放内存的需求的场景。

这篇关于【QT】关于Qt::WA_DeleteOnClose的使用问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853560

相关文章

使用Python开发Markdown兼容公式格式转换工具

《使用Python开发Markdown兼容公式格式转换工具》在技术写作中我们经常遇到公式格式问题,例如MathML无法显示,LaTeX格式错乱等,所以本文我们将使用Python开发Markdown兼容... 目录一、工具背景二、环境配置(Windows 10/11)1. 创建conda环境2. 获取XSLT

Python中Flask模板的使用与高级技巧详解

《Python中Flask模板的使用与高级技巧详解》在Web开发中,直接将HTML代码写在Python文件中会导致诸多问题,Flask内置了Jinja2模板引擎,完美解决了这些问题,下面我们就来看看F... 目录一、模板渲染基础1.1 为什么需要模板引擎1.2 第一个模板渲染示例1.3 模板渲染原理二、模板

浅析如何使用xstream实现javaBean与xml互转

《浅析如何使用xstream实现javaBean与xml互转》XStream是一个用于将Java对象与XML之间进行转换的库,它非常简单易用,下面将详细介绍如何使用XStream实现JavaBean与... 目录1. 引入依赖2. 定义 JavaBean3. JavaBean 转 XML4. XML 转 J

使用Python创建一个功能完整的Windows风格计算器程序

《使用Python创建一个功能完整的Windows风格计算器程序》:本文主要介绍如何使用Python和Tkinter创建一个功能完整的Windows风格计算器程序,包括基本运算、高级科学计算(如三... 目录python实现Windows系统计算器程序(含高级功能)1. 使用Tkinter实现基础计算器2.

MySQL主从同步延迟问题的全面解决方案

《MySQL主从同步延迟问题的全面解决方案》MySQL主从同步延迟是分布式数据库系统中的常见问题,会导致从库读取到过期数据,影响业务一致性,下面我将深入分析延迟原因并提供多层次的解决方案,需要的朋友可... 目录一、同步延迟原因深度分析1.1 主从复制原理回顾1.2 延迟产生的关键环节二、实时监控与诊断方案

在.NET平台使用C#为PDF添加各种类型的表单域的方法

《在.NET平台使用C#为PDF添加各种类型的表单域的方法》在日常办公系统开发中,涉及PDF处理相关的开发时,生成可填写的PDF表单是一种常见需求,与静态PDF不同,带有**表单域的文档支持用户直接在... 目录引言使用 PdfTextBoxField 添加文本输入域使用 PdfComboBoxField

SQLyog中DELIMITER执行存储过程时出现前置缩进问题的解决方法

《SQLyog中DELIMITER执行存储过程时出现前置缩进问题的解决方法》在SQLyog中执行存储过程时出现的前置缩进问题,实际上反映了SQLyog对SQL语句解析的一个特殊行为,本文给大家介绍了详... 目录问题根源正确写法示例永久解决方案为什么命令行不受影响?最佳实践建议问题根源SQLyog的语句分

Git可视化管理工具(SourceTree)使用操作大全经典

《Git可视化管理工具(SourceTree)使用操作大全经典》本文详细介绍了SourceTree作为Git可视化管理工具的常用操作,包括连接远程仓库、添加SSH密钥、克隆仓库、设置默认项目目录、代码... 目录前言:连接Gitee or github,获取代码:在SourceTree中添加SSH密钥:Cl

Python中模块graphviz使用入门

《Python中模块graphviz使用入门》graphviz是一个用于创建和操作图形的Python库,本文主要介绍了Python中模块graphviz使用入门,具有一定的参考价值,感兴趣的可以了解一... 目录1.安装2. 基本用法2.1 输出图像格式2.2 图像style设置2.3 属性2.4 子图和聚

windows和Linux使用命令行计算文件的MD5值

《windows和Linux使用命令行计算文件的MD5值》在Windows和Linux系统中,您可以使用命令行(终端或命令提示符)来计算文件的MD5值,文章介绍了在Windows和Linux/macO... 目录在Windows上:在linux或MACOS上:总结在Windows上:可以使用certuti