【OpenGL开发】PyQt在关闭应用程序时没有运行析构函数的问题

PyQt在关闭应用程序时没有运行析构函数的问题

在这里插入图片描述

目录

  • 一、说明
  • 二、python的析构函数
  • 三、QT5 存在一些问题
  • 四、PyQt5 存在一些问题
  • 五、OpenGL的析构问题

一、说明

   应用QT做程序界面,在程序退出的时候,需要调用析构函数释放资源,这个操作在Python程序中,虽然不调用析构函数,资源也可以释放。在QOpenGLWidget中,会产生一系列的buff对象,如果不能正确释放,程序将出现状况,如何解决?

   但是,出现讨厌的错误提示,比如下图:
在这里插入图片描述

二、python的析构函数

   在PyQt中,当一个类的实例被销毁时,Python会自动调用它的析构函数(即__del__方法)。析构函数主要用于释放资源(例如关闭文件、断开网络连接等),以确保在对象被销毁之前进行必要的清理工作。

from PyQt5.QtWidgets import QApplication, QMainWindowclass MyWindow(QMainWindow):def __init__(self):super().__init__()def __del__(self):print("析构函数被调用")app = QApplication([])
window = MyWindow()
window.show()
app.exec_()

   在PyQt中,当一个类的实例被销毁时,Python会自动调用它的析构函数(即__del__方法)。析构函数主要用于释放资源(例如关闭文件、断开网络连接等),以确保在对象被销毁之前进行必要的清理工作。

三、QT5 存在一些问题

   按照文库的说法,“如果子窗体初始化了父窗体的parent,只有父窗体析构时才执行自己的析构函数。”

   根据我的经验,系统默认的构造函数中parent都有默认值0,而构造函数的实现中,都有初始化列表指定父类的parent为当前parent,如果不指定,也就是0。这里还不能把parent指定位父窗体,否则子窗体会作为一个父窗体当中的“部件”而存在。父类和父窗体不是一个东西。所以文库当中的说法我暂时不太明白。

   我的想法是这样,既是不初始化父类的parent,它的构造函数中parent参数依然会有默认值为空指针,所以是否执行析构函数,和初始化父类构造函数我想不出联系。

   但是文库中给出了解决方法,在子窗体构造函数中加一句即可:

setAttribute(Qt::WA_DeleteOnClose);

   这才是最重要的。根据qt的文档,这个属性就是在close时delete。

Qt::WA_DeleteOnClose 55Makes Qt delete this widget when the widget has accepted the close event (see QWidget::closeEvent()).

   之所以说是坑,就是每次设计窗体时,总觉得想当然可以关闭时执行析构,但事实上必须加这一句,总会忘掉,特此记录,提醒自己。

四、PyQt5 存在一些问题

   有时在关闭应用程序时,PyQt不会自动调用类的析构函数,可能导致一些资源无法正常释放。这可能是因为应用程序的主事件循环在关闭窗口时仍在运行,从而导致类的实例无法被销毁。
   为了解决这个问题,我们可以通过重写QMainWindow的closeEvent方法来手动触发析构函数的调用。

from PyQt5.QtWidgets import QApplication, QMainWindowclass MyWindow(QMainWindow):def __init__(self):super().__init__()def __del__(self):print("析构函数被调用")def closeEvent(self, event):self.__del__()  # 手动调用析构函数event.accept()app = QApplication([])
window = MyWindow()
window.show()
app.exec_()

   在上面的示例代码中,我们重写了closeEvent方法,并在其中手动调用了析构函数。通过这种方式,我们可以确保在关闭窗口时,析构函数会被正确地调用。

   在PyQt中,当一个类的实例被销毁时,Python会自动调用它的析构函数(即__del__方法)。析构函数主要用于释放资源(例如关闭文件、断开网络连接等),以确保在对象被销毁之前进行必要的清理工作。

五、OpenGL的析构问题

OpenGL对自身的上下文是非常敏感的,稍有不慎可能就会导致内存泄漏,或者没有释放正确,就比如 QOpenGLVertexArrayObject::destroy() failed to restore current context 问题,由于上下文的问题没有办法正确的释放QOpenGLVertexArrayObject VAO对象。

发生的原因:我想在QOpenGLWidget的析构函数 delete 掉我的网格类对象,网格类对象内使用了VAO对象也就是QOpenGLVertexArrayObject 这个类,两个类的析构大致如下

Mesh类:

Mesh::~Mesh(){m_VBO.destroy();m_VAO.destroy();
}
MyOpenGLWidget类:MyOpenGLWidget::~MyOpenGLWidget(){delete mesh;
}

在关闭窗口后控制台面板就输出了这个问题

在这里插入图片描述

解决方法:

这个问题的原因就是因为在OpenGL窗口结束了之后,最后在析构的时候还有使用到OpenGL的东西,就是delete mesh对象时mesh的析构又调用了QtOpenGL相关内容导致的OpenGL上下文不正确。

所以在MyOpenGLWidget的析构函数中加入下面的函数来确保上下文正确。

MyOpenGLWidget::~MyOpenGLWidget(){// 确保释放opengl资源时上下文正确makeCurrent();delete mesh;doneCurrent();}

这也是一个解决办法,如果还有其他办法再说吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/619100.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汇编语言知识点整理(应付考试专用,想学习找其他的)

1 基础知识 1.1 信息在计算机内部的表示和存储 1.1.1 信息存储的基本概念 信息在计算机内部是以二进制数据的形式在存储器中存取的。介绍两个基本概念: 位(Bit) 计算机中最小的数据单位,一位有0、1两状态。Bit是计算机中最小…

论文笔记:SmartPlay : A Benchmark for LLMs as Intelligent Agents

iclr 2024 reviewer评分 5688 引入了 SmartPlay,一种从 6 种不同游戏中提取的基准 衡量LLM作为智能体的能力 1 智能代理所需的能力 论文借鉴游戏设计的概念,确定了智能LLM代理的九项关键能力,并为每项能力确定了多个等级: 长文…

LLM-大模型演化分支树、GPT派发展阶段及训练流程图、Infini-Transformer说明

大模型是怎么演进的? Encoder Only: 对应粉色分支,即BERT派,典型模型: BERT 自编码模型(Autoencoder Model):通过重建句子来进行预训练,通常用于理解任务,如文本分类和阅…

<计算机网络自顶向下> TCPUDP套接字编程

应用实现:源端的应用进程交换报文实现应用协议,来实现各种各样的网络应用(dash,email, etc) 而应用层通信不可以直接通信,需要借助下层的服务才可以进行,通过层间接口交给下层,通过…

面试八股——Spring——AOP与事务

AOP的定义 事务的实现 事务的失效场景 异常捕获处理 下图中由于②导致异常: 原因: 解决办法:自己抛出一个非检查异常(具体原因看“抛出检查异常”)。 抛出检查异常 由于①出错,导致抛出了检查异常 原因&…

【Linux】CentOS 7安装后没有图形界面

专栏文章索引:Linux 有问题可私聊:QQ:3375119339 目录 一、项目场景 二、问题描述 三、原因分析 四、解决方案 1.当前处于命令行界面,可以切换为图形界面 2.安装时没有安装图形界面,选择了Minimal Install 3.下…

专业照片编辑软件ON1 Photo RAW 2024 mac/win

ON1 Photo RAW 2024 for Mac是一款集专业性与易用性于一体的照片编辑软件。它拥有简洁直观的用户界面,即便对于摄影新手,也能快速上手。软件支持RAW格式照片处理,能够完整保留照片原始信息,让后期调整更加灵活。 在功能方面&#…

数据链路层(上):以太网、二层交换机和网络风暴

目录 数据链路层知识概览 数据链路层设备 1、二层交换机 2、拓展:二层交换机与三层交换机有啥区别? 3、广播风暴 4、交换机以太网接口的工作模式 数据链路层的功能 数据链路层--以太网 1、以太网是什么? 2、以太网地址 数据链路层知…

Unity 中消息提醒框

Tooltip 用于ui布局 using System.Collections; using System.Collections.Generic; using UnityEngine; using TMPro; using UnityEngine.UI;[ExecuteInEditMode()] // 可以在编辑模式下运行public class Tooltip : MonoBehaviour {public TMP_Text header; // 头部文本publi…

JS/TS笔记学习1

周末总得学点什么吧~ 奥利给! 跑火车 递归 减速 let currentIndex 0; let speed 500; // 初始速度,单位是毫秒 let decrement 20; // 每次迭代速度减少的量 const cells document.querySelectorAll(.cell); function highlightCell() { cells.forEach(…

Redis中的订阅发布(一)

订阅发布 概述 Redis的发布与订阅功能由PUBLISH、SUBSCRIBE、PSUBSCRIBE等命令组成。通过执行SUBSCRIBER命令,客户端可以订阅一个或多个频道,从而成为这些频道的订阅者(subscribe): 每当有其他客户端向被订阅的频道发送消息(message)时&…