Qt(PySide6):QMdiSubWindow点击X不触发closeEvent且未销毁
MDI子窗口closeEvent不触发及对象未销毁问题解决
问题根源
你定义的closeEvent属于ExampleWindow类,但MDI区域中实际响应用户关闭操作的是QMdiSubWindow容器,而非作为其widget的ExampleWindow。此外,Qt默认设置下,QMdiSubWindow点击关闭仅会隐藏窗口,不会销毁对象,因此destroyed信号也不会触发。
解决方案
方案1:给QMdiSubWindow安装事件过滤器
在ExampleWindow中捕获QMdiSubWindow的关闭事件,同时设置关闭时销毁对象:
from PyQt5.QtCore import QEvent, Qt from PyQt5.QtWidgets import QMainWindow, QMdiSubWindow class ExampleWindow(QMainWindow): def __init__(self, parent): super(ExampleWindow, self).__init__(parent) self.parent_window = parent self.ui = self.parent_window.loader.load("Code/UI/example.ui", None) self.ui.setWindowTitle("ExampleTitle") self.example_subwindow = None def loadWindow(self): self.example_subwindow = QMdiSubWindow() self.example_subwindow.setWidget(self.ui) self.parent_window.ui.mdiArea.addSubWindow(self.example_subwindow) # 为子窗口安装事件过滤器 self.example_subwindow.installEventFilter(self) self.example_subwindow.show() def eventFilter(self, obj, event): if obj == self.example_subwindow and event.type() == QEvent.Close: # 在这里执行销毁前的操作 print("执行关闭前的清理逻辑") # 设置关闭时自动销毁对象 self.example_subwindow.setAttribute(Qt.WA_DeleteOnClose) event.accept() return True return super().eventFilter(obj, event)
方案2:自定义QMdiSubWindow子类并重写closeEvent
创建继承自QMdiSubWindow的子类,在其中重写关闭事件:
from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QMainWindow, QMdiSubWindow class CustomMdiSubWindow(QMdiSubWindow): def closeEvent(self, event): # 执行关闭前的操作 print("自定义子窗口关闭前的处理") # 开启关闭销毁属性 self.setAttribute(Qt.WA_DeleteOnClose) event.accept() class ExampleWindow(QMainWindow): def __init__(self, parent): super(ExampleWindow, self).__init__(parent) self.parent_window = parent self.ui = self.parent_window.loader.load("Code/UI/example.ui", None) self.ui.setWindowTitle("ExampleTitle") def loadWindow(self): self.example_subwindow = CustomMdiSubWindow() self.example_subwindow.setWidget(self.ui) self.parent_window.ui.mdiArea.addSubWindow(self.example_subwindow) self.example_subwindow.show()
方案3:绑定destroyed信号(需先开启销毁属性)
通过设置WA_DeleteOnClose让窗口关闭时销毁,再绑定destroyed信号执行后续操作:
from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QMainWindow, QMdiSubWindow class ExampleWindow(QMainWindow): def __init__(self, parent): super(ExampleWindow, self).__init__(parent) self.parent_window = parent self.ui = self.parent_window.loader.load("Code/UI/example.ui", None) self.ui.setWindowTitle("ExampleTitle") def on_subwindow_destroyed(self): # 窗口销毁时执行的操作 print("子窗口已销毁,执行清理") def loadWindow(self): self.example_subwindow = QMdiSubWindow() self.example_subwindow.setWidget(self.ui) self.parent_window.ui.mdiArea.addSubWindow(self.example_subwindow) # 开启关闭自动销毁 self.example_subwindow.setAttribute(Qt.WA_DeleteOnClose) # 绑定销毁信号 self.example_subwindow.destroyed.connect(self.on_subwindow_destroyed) self.example_subwindow.show()
关键说明
- 必须设置
Qt.WA_DeleteOnClose属性,否则QMdiSubWindow关闭后仅隐藏,不会触发对象销毁。 - 关闭事件的处理目标是
QMdiSubWindow容器,而非其内部的widget,因此需要针对容器类处理事件。
内容的提问来源于stack exchange,提问作者phill_c
相关产品推荐
相关产品推荐

