Как очистить оперативную память после закрытия второго окна? - PullRequest
2 голосов
/ 26 апреля 2019

В примере, когда программа запускается, 18 МБ ОЗУ занято. При запуске второго окна еще 4 МБ будет занято ОЗУ. Когда мы закрываем второе окно, занятая память не будет возвращена в ОЗУ, и если второе окно открывается во второй раз, то снова будет занято 4 МБ ОЗУ. Каково ваше решение для этой проблемы? Это пример PyQt4, а мое приложение PyQt5.

Этот пример по этой ссылке: PyQT: как открыть новое окно

Если возможно, предложите программу, которая открывает второе окно с основным методом и не занимает место в ОЗУ после закрытия.

from PyQt4 import QtGui, QtCore
import sys

class Second(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Second, self).__init__(parent)


class First(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(First, self).__init__(parent)
        self.pushButton = QtGui.QPushButton("click me")
        self.setCentralWidget(self.pushButton)

        self.pushButton.clicked.connect(self.on_pushButton_clicked)
        self.dialogs = list()

    def on_pushButton_clicked(self):
        dialog = Second(self)
        self.dialogs.append(dialog)
        dialog.show()

    def main():
        app = QtGui.QApplication(sys.argv)
        main = First()
        main.show()
        sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Пример в PyQt5

from PyQt5 import QtCore, QtGui, QtWidgets, uic
import sys

class Second(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Second, self).__init__(parent)


class First(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(First, self).__init__(parent)
        self.pushButton = QtWidgets.QPushButton("click me")
        self.setCentralWidget(self.pushButton)

        self.pushButton.clicked.connect(self.on_pushButton_clicked)
        self.dialogs = list()


    def on_pushButton_clicked(self):
        dialog = Second(self)
        self.dialogs.append(dialog)
        dialog.show()


def main():
    app = QtWidgets.QApplication(sys.argv)
    main = First()
    main.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

1 Ответ

3 голосов
/ 26 апреля 2019

В PyQt, в зависимости от того, как вы конфигурируете объект, вашим свойством может управлять C ++ или Python.В случае объекта QObject, такого как QMainWindow, если передается родительский объект, обработка памяти выполняется на C ++, и правило Qt указывает, что дочерний элемент умирает, только если родительский элемент умирает или дочерний элемент явно удаляется с помощью deleteLater.Итак, второй жизненный цикл зависит от первого, то есть даже когда вы закрываете окно, объект не удаляется.Чтобы окно было удалено при закрытии окна, вы должны активировать атрибут Qt :: WA_DeleteOnClose , поэтому решение состоит в том, чтобы добавить его во Второй класс:

class Second(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(Second, self).__init__(parent)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose) # <---

Если вы собираетесь использовать контейнер для сохранения ссылки на объекты, у вас могут возникнуть проблемы, потому что, когда C ++ удаляет объект, он не уведомляет контейнер.Таким образом, есть следующие варианты, чтобы избежать этих проблем:

  • Не используйте контейнер.
  • Используйте weakref.ref () , чтобы, когда объектудалено, оно также удаляется из контейнера:
def on_pushButton_clicked(self):
    dialog = Second(self)
    self.dialogs.append(weakref.ref(dialog, self.dialogs.remove))
    dialog.show()
  • Используйте уничтоженный сигнал для удаления объектов из контейнера:
import sip
# ...
class First(QtWidgets.QMainWindow):
    # ...
    def on_pushButton_clicked(self):
        dialog = Second(self)
        dialog.destroyed.connect(self.on_destroyed)
        self.dialogs.append(dialog)
        dialog.show()

    @QtCore.pyqtSlot('QObject*')
    def on_destroyed(self, obj):
        self.dialogs = [dialog for dialog in self.dialogs if not sip.isdeleted(dialog)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...