在MC架构中,相互引用会导致内存泄漏。我如何更改一个好的设计程序?
In the MC architecture, mutual references cause memory leaks. How do I change a good design program?
点击按钮,QTabWidget 将添加一个标签(患者对象)。
我是这样设计的。
首先模型请求网络获取数据后调用patient方法显示数据
其次,患者会主动使用模型中的数据。
所以我定义了self.model=Model()和self.view=view,但是这样就产生了问题。患者和模型相互引用,这将导致内存泄漏。所以当我关闭标签时,我不得不删除 patient.model。属性之间不再相互引用,解决了内存泄露问题
但是,在我的项目中,我有很多视图和模型相互引用的情况。我需要把它们都找出来,然后在关闭标签的时候关闭它们之间的关系。我认为这种设计在内存泄漏方面有点薄弱。你能给我一些更好的设计建议吗?非常感谢。
import sys
from PyQt4 import QtGui
from PyQt4.QtGui import QTabWidget, QHBoxLayout, QWidget, QPushButton
class Model(object):
def __init__(self, view):
self.view = view
class Patient(QWidget):
def __init__(self):
super(Patient, self).__init__()
self.model = Model(self)
self.data = [map(lambda x: {'name': 'ken'}, [x for x in range(10000000)])]
class Tab(QTabWidget):
def __init__(self):
super(Tab, self).__init__()
self.setTabsClosable(True)
self.tabCloseRequested.connect(self.delete)
def add(self):
self.addTab(Patient(), 'name')
def delete(self, index):
patient = self.widget(index)
self.removeTab(index)
import sip
sip.delete(patient)
del patient.model
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.hbox = QHBoxLayout()
self.setLayout(self.hbox)
self.tab = Tab()
self.hbox.addWidget(self.tab)
btn = QPushButton()
btn.clicked.connect(self.click)
self.hbox.addWidget(btn)
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle("PyQt")
self.show()
def click(self):
self.tab.add()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
如果您总是使用 Model 和 Patient 类,则可以使用 destroyed()
信号在小部件被删除时收到通知,并删除模型。
由于 deleteLater()
还负责断开与销毁对象相关的所有插槽,因此不能在其自己的实例上调用该方法。为了避免这种情况,使用 lambda 可以解决这个问题。
class Patient(QWidget):
def __init__(self):
super(Patient, self).__init__()
self.model = Model(self)
self.data = [map(lambda x: {'name': 'ken'}, [x for x in range(10000000)])]
self.destroyed.connect(lambda: self.aboutToBeDeleted())
def aboutToBeDeleted(self):
del self.model
class Tab(QTabWidget):
#...
def delete(self, index):
patient = self.widget(index)
self.removeTab(index)
patient.deleteLater()
这应该会处理所有事情,包括断开与 patient
相关的所有插槽和信号。调用 deleteLater()
也应该足够了,而不是使用 sip.delete (我相信无论如何都是由 deleteLater 完成的)。
点击按钮,QTabWidget 将添加一个标签(患者对象)。
我是这样设计的。
首先模型请求网络获取数据后调用patient方法显示数据
其次,患者会主动使用模型中的数据。
所以我定义了self.model=Model()和self.view=view,但是这样就产生了问题。患者和模型相互引用,这将导致内存泄漏。所以当我关闭标签时,我不得不删除 patient.model。属性之间不再相互引用,解决了内存泄露问题
但是,在我的项目中,我有很多视图和模型相互引用的情况。我需要把它们都找出来,然后在关闭标签的时候关闭它们之间的关系。我认为这种设计在内存泄漏方面有点薄弱。你能给我一些更好的设计建议吗?非常感谢。
import sys
from PyQt4 import QtGui
from PyQt4.QtGui import QTabWidget, QHBoxLayout, QWidget, QPushButton
class Model(object):
def __init__(self, view):
self.view = view
class Patient(QWidget):
def __init__(self):
super(Patient, self).__init__()
self.model = Model(self)
self.data = [map(lambda x: {'name': 'ken'}, [x for x in range(10000000)])]
class Tab(QTabWidget):
def __init__(self):
super(Tab, self).__init__()
self.setTabsClosable(True)
self.tabCloseRequested.connect(self.delete)
def add(self):
self.addTab(Patient(), 'name')
def delete(self, index):
patient = self.widget(index)
self.removeTab(index)
import sip
sip.delete(patient)
del patient.model
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.hbox = QHBoxLayout()
self.setLayout(self.hbox)
self.tab = Tab()
self.hbox.addWidget(self.tab)
btn = QPushButton()
btn.clicked.connect(self.click)
self.hbox.addWidget(btn)
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle("PyQt")
self.show()
def click(self):
self.tab.add()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
如果您总是使用 Model 和 Patient 类,则可以使用 destroyed()
信号在小部件被删除时收到通知,并删除模型。
由于 deleteLater()
还负责断开与销毁对象相关的所有插槽,因此不能在其自己的实例上调用该方法。为了避免这种情况,使用 lambda 可以解决这个问题。
class Patient(QWidget):
def __init__(self):
super(Patient, self).__init__()
self.model = Model(self)
self.data = [map(lambda x: {'name': 'ken'}, [x for x in range(10000000)])]
self.destroyed.connect(lambda: self.aboutToBeDeleted())
def aboutToBeDeleted(self):
del self.model
class Tab(QTabWidget):
#...
def delete(self, index):
patient = self.widget(index)
self.removeTab(index)
patient.deleteLater()
这应该会处理所有事情,包括断开与 patient
相关的所有插槽和信号。调用 deleteLater()
也应该足够了,而不是使用 sip.delete (我相信无论如何都是由 deleteLater 完成的)。