In the below example, I open new child windows from the main one. For each new window, I add a reference to it in a list to keep track on all new window (I have plenty of them in my whole software). My issue is when I have opened several windows and I have closed some of them, the references to those closed windows still appear in the list:
1 window open
[<__main__.window object at 0x000002B91B7D1798>]
2 windows open
[<__main__.window object at 0x000002B91B7D1798>, <__main__.window object at 0x000002B91B7D19D8>]
3 windows open
[<__main__.window object at 0x000002B91B7D1798>, <__main__.window object at 0x000002B91B7D19D8>, <__main__.window object at 0x000002B91B7D1C18>]
4 windows open
[<__main__.window object at 0x000002B91B7D1798>, <__main__.window object at 0x000002B91B7D19D8>, <__main__.window object at 0x000002B91B7D1C18>, <__main__.window object at 0x000002B91B7D1E58>]
hereI closed the first two windows, so 3 windows are opened, but I still have :
[<__main__.window object at 0x000002B91B7D1798>, <__main__.window object at 0x000002B91B7D19D8>, <__main__.window object at 0x000002B91B7D1C18>, <__main__.window object at 0x000002B91B7D1E58>, <__main__.window object at 0x000002B91B8640D8>]
How can I really close the child window and don't have their reference in my list? Otherwise, they are not closed obviously.
here's the MRE
from PyQt5.QtWidgets import *
import sys
class window(QMainWindow):
def __init__(self, parent=None ):
super(window, self).__init__()
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.HBOX = QVBoxLayout()
self.PB = QPushButton('open new window')
self.PB.clicked.connect(self.new_window)
self.HBOX.addWidget(self.PB)
self.centralWidget.setLayout(self.HBOX)
self.windows_list = []
def new_window(self):
self.windows_list.append(window(self))
self.windows_list[-1].show()
print(self.windows_list)
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = window()
ex.show()
sys.exit(app.exec_())
Keep in mind that closing a window does not delete it (unless the Qt.WA_DeleteOnClose
attribute is set, which is not by default).
A possible solution is to override the closeEvent
and send a custom signal.
class Window(QMainWindow):
closed = QtCore.pyqtSignal(object)
# ...
def new_window(self):
new_window = Window(self)
self.windows_list.append(new_window)
new_window.show()
new_window.closed.connect(self.window_list.remove)
def closeEvent(self, event):
self.closed.emit(self)
Another possibility is to always set the Qt.WA_DeleteOnClose
attribute and connect to the destroyed
signal, but in that case you cannot rely on the signal argument (it doesn't match the actual deleted window), and a lambda with the window instance must be used instead:
class Window(QMainWindow):
# ...
def new_window(self):
new_window = Window(self)
self.windows_list.append(new_window)
new_window.setAttribute(Qt.WA_DeleteOnClose)
new_window.show()
new_window.destroyed.connect(lambda: self.windows_list.remove(new_window))
Note that I capitalized the class name, as classes should not use lower cased names.