【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

相关文章

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Qt中QGroupBox控件的实现

《Qt中QGroupBox控件的实现》QGroupBox是Qt框架中一个非常有用的控件,它主要用于组织和管理一组相关的控件,本文主要介绍了Qt中QGroupBox控件的实现,具有一定的参考价值,感兴趣... 目录引言一、基本属性二、常用方法2.1 构造函数 2.2 设置标题2.3 设置复选框模式2.4 是否

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

《如何解决idea的Module:‘:app‘platform‘android-32‘notfound.问题》:本文主要介绍如何解决idea的Module:‘:app‘platform‘andr... 目录idea的Module:‘:app‘pwww.chinasem.cnlatform‘android-32

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、