0

I encountered a problem. When adding subwindow to a mdiarea, the memory occupied by the whole program will gradually increase, but when the subwindow in mdiarea is closed, the resource manager cannot reclaim its memory, here bellow is a demo-code, I have Created a mainwindow with a tabwidget, which contains a series of tabs, each tab contains an mdiArea widget, and in the mdiarea you can add or delete multiple subwindows.:

# -*- coding: utf-8 -*-

"""

"""

import sys
from PyQt5 import QtWidgets, QtCore, sip

import matplotlib

import weakref

matplotlib.use("Qt5Agg")


class SubWindow(QtWidgets.QMainWindow):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(300, 100)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)


class TabWidget(QtWidgets.QWidget):
    """
    """
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)

        self.vLayout = QtWidgets.QVBoxLayout(self)
        self.mdiArea = QtWidgets.QMdiArea(self)
        self.vLayout.addWidget(self.mdiArea)
        self.subWindows = []

    def insertSubWindow(self):
        sub_window = SubWindow(self)

        sub_window.destroyed.connect(self.removeSubWindow)

        self.subWindows.append(weakref.ref(sub_window, self.subWindows.remove))

        self.mdiArea.addSubWindow(sub_window)  # if this line is removed, then memory can be reclaimed.

        sub_window.show()

    def removeSubWindow(self):
        print(self.mdiArea.subWindowList())


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(800, 400)
        v_layout = QtWidgets.QVBoxLayout()

        self.tabWidget = QtWidgets.QTabWidget(self)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.tabCloseRequested.connect(self.removeTab)
        self.tabs = list()
        self.tabIndex = 0

        h_layout = QtWidgets.QHBoxLayout()
        self.pushButton_AddTab = QtWidgets.QPushButton('Add Tab', self)
        h_layout.addWidget(self.pushButton_AddTab)
        self.pushButton_AddFig = QtWidgets.QPushButton('Add Fig', self)
        h_layout.addWidget(self.pushButton_AddFig)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        h_layout.addItem(spacerItem)

        v_layout.addLayout(h_layout)
        v_layout.addWidget(self.tabWidget)

        widget = QtWidgets.QWidget()
        widget.setLayout(v_layout)
        self.setCentralWidget(widget)

        self.pushButton_AddTab.clicked.connect(self.insertTab)
        self.pushButton_AddFig.clicked.connect(self.insertFig)

    def insertTab(self):
        tab_name = 'Tab ' + str(self.tabIndex)
        self.tabIndex += 1
        new_tab = TabWidget(self)
        # new_tab.destroyed.connect(self.removeTab)
        self.tabs.append(weakref.ref(new_tab, self.tabs.remove))
        self.tabWidget.addTab(new_tab, tab_name)

    def removeTab(self, index):
        self.tabWidget.removeTab(index)

    def insertFig(self):
        tab_current = self.tabWidget.currentWidget()
        tab_current.insertSubWindow()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    mw = MainWindow()
    mw.show()
    app.exec_()
bactone
  • 107
  • 1
  • 8
  • How do you measure the memory of the program? – eyllanesc Nov 25 '21 at 06:33
  • @eyllanesc, i just monitoring the resource manager – bactone Nov 25 '21 at 06:39
  • @eyllanesc Hi, eyllanesc, I have tried your answer post at the [link]https://stackoverflow.com/questions/55870336/how-to-empty-the-ram-after-closing-the-second-window – bactone Nov 25 '21 at 06:42
  • mmm, do not use that tool, it does not serve to measure program memory, it is only a distraction for users. You must use tools like https://pypi.org/project/memory-profiler/, and I have used that tool and I don't see what you point to. – eyllanesc Nov 25 '21 at 06:43
  • @eyllanesc, hi, i tried to use memory-profiler, but how to monitoring the memory cost when add or remove subwindow, I add some code: `@ profile def main(): app = QtWidgets.QApplication(sys.argv) mw = MainWindow() mw.show() app.exec_() if __name__ == '__main__': main()`, but it doesn't present detail information ? – bactone Nov 25 '21 at 07:09
  • See the *Time-based memory usage* section in README – eyllanesc Nov 25 '21 at 07:12
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/239565/discussion-between-bactone-and-eyllanesc). – bactone Nov 25 '21 at 07:27
  • After checking with memory profiler it does seem like the memory is not being released for deleted windows, but it also seems that memory is being reused (as creating new windows again after deleting all the previous doesn't increase memory usage). – musicamante Nov 25 '21 at 10:32
  • 1
    @bactone note that the `WA_DeleteOnClose` flag has to be set on the subwindow, not the widget, and it's also only necessary when using `addSubWindow` with a custom QMdiSubWindow, as when using a widget it's automatically set for the QMdiSubWindow that QMdiArea creates on its own. – musicamante Nov 25 '21 at 10:33

0 Answers0