python - 关闭第二个窗口后如何清空 RAM?
问题描述
在示例中,当程序运行时,占用了 18 MB 的 RAM。当第二个窗口运行时,另外 4 MB 将被 RAM 占用。当我们关闭第二个 Window 时,所占用的内存不会返回到 RAM,如果第二次打开第二个 Window,那么又会占用 4MB 的 RAM。你对这个问题的解决方案是什么?这个例子是 PyQt4 而我的应用是 PyQt5。
这个例子来自这个链接: PyQT: how to open new window
如果可能的话,提出一个程序,用原理方法打开第二个窗口,关闭后不占用RAM空间。
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()
解决方案
在 PyQt 中,根据您配置对象的方式,您的属性可以由 C++ 或 Python 管理。对于 QObject(例如 QMainWindow),如果传递了父级,则内存处理是 C++,并且 Qt 规则表明,只有当父级死亡或子级被 deleteLater 显式删除时,子级才会死亡。所以 Second 的生命周期取决于 First,也就是说,即使你关闭了窗口,对象也不会被删除。对于要在窗口关闭时删除的窗口,您必须激活属性Qt::WA_DeleteOnClose,因此解决方案是将其添加到 Second 类中:
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()
- 使用destroyed信号从容器中移除对象:
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)]
推荐阅读
- python - 将派生字段更改为浮动并获取派生字段的平均值
- javascript - 覆盖 SVG 图形 - 与 JavaScript 文件相矛盾 (Plotly / Distill.pub)
- neo4j - Neo4j 升级 - https://yum.neo4j.org/stable/repodata/repomd.xml:[Errno 14] HTTPS 错误 503 - 服务不可用
- python - 如何在 Mac 上成功安装 OpenPYXL?
- swift - 编辑 TextField 将 Animated UIView 移动到其原始位置 Swift
- node.js - findOneAndUpdate 不返回原始文档
- windows - 如何获取当前用户组的所有 SID
- javascript - 找不到文件。NodeJS、MySQL、Visual Studio 代码
- java - Lambda 和 Runnable
- blockchain - 在 web3j 中使用 ganache 帐户