#python #qt #pyqt
#python #qt #pyqt
Вопрос:
Используя приведенный ниже код, __del__
метод моего виджета предварительного просмотра никогда не вызывается. Если я раскомментирую строку « del window
«, это произойдет. Почему?
#!/usr/bin/env python
from PyQt4 import QtGui
class Preview(QtGui.QWidget):
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent)
def __del__(self):
print("Deleting Preview")
class PreviewWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.widget = Preview(self)
self.setCentralWidget(self.widget)
def __del__(self):
print("Deleting PreviewWindow")
if __name__ == "__main__":
app = QtGui.QApplication(["Dimension Preview"])
window = PreviewWindow()
window.show()
app.exec()
# del window
Комментарии:
1. У меня это работает на Fedora Linux 14 (PyQt 4.8.3, Python 2.7). Однако мне пришлось изменить app.exec() на app.exec_().
2.@xioxox. Вы уверены, что вызываются оба
__del__
метода?3. @xioxox. Для меня, используя pyqt-4.8.6, вызывается только один
__del__
метод; но с pyqt-4.8.5, оба делают. Интересно, есть ли ошибка в последней версии?
Ответ №1:
Если у QObject
подкласса есть родительский элемент, Qt удалит его при удалении родительского элемента. С другой стороны, если у QObject
подкласса нет родителя, он (в конечном итоге) будет удален python.
Надеюсь, этот пример несколько прояснит ситуацию:
from PyQt4 import QtGui
class Widget(QtGui.QWidget):
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent)
self.destroyed.connect(self.handleDestroyed)
def __del__(self):
print ('__del__:', self)
def handleDestroyed(self, source):
print ('destroyed:', source)
class Foo(Widget):
def __init__(self, parent):
Widget.__init__(self, parent)
class Bar(Widget):
def __init__(self, parent):
Widget.__init__(self, parent)
class Window(Widget):
def __init__(self, parent=None):
Widget.__init__(self, parent)
self.foo = Foo(self)
self.bar = Bar(None)
if __name__ == "__main__":
app = QtGui.QApplication([__file__, '-widgetcount'])
window = Window()
window.show()
app.exec_()
Какие результаты:
__del__: <__main__.Window object at 0x88f514c>
destroyed: <__main__.Foo object at 0x88f5194>
__del__: <__main__.Bar object at 0x88f51dc>
Widgets left: 0 Max widgets: 4
Редактировать
Если подумать, то, похоже, в некоторых версиях PyQt4 может быть ошибка (или, по крайней мере, разница в поведении).
В качестве возможного обходного пути кажется, что создание двух имен python для основного виджета, а затем явное удаление каждого из них может помочь гарантировать, что обе стороны объекта C и python будут уничтожены.
Если в приведенный выше скрипт добавлена следующая строка:
tmp = window; del tmp, window
Затем вывод становится:
__del__: <__main__.Window object at 0x8d3a14c>
__del__: <__main__.Foo object at 0x8d3a194>
__del__: <__main__.Bar object at 0x8d3a1dc>
Widgets left: 0 Max widgets: 4
Комментарии:
1. Значит
__del__
, ожидаемое поведение в этом случае никогда не вызывается? Это приводит к утечкам в моем приложении. И использованиеparent=None
не поможет, если вы это сделаетеself.setCentralWidget(self.widget)
.2. @TavianBarnes. Я отредактировал свой ответ и добавил возможное решение вашей проблемы.
3. Для записи это был ответ: riverbankcomputing.com/pipermail/pyqt/2011-November/030656.html