慣用的な Qt と思われるものを使用して、これを達成できるいくつかの方法を次に示します。
- 親で を使用し
closeEvent
て、各子でクリーンアップを直接実行します。
destroyed
親のシグナルを使用して、各子で間接的にクリーンアップを呼び出します
- 親の からカスタム シグナルを発信し
closeEvent
、子のクリーンアップに直接接続します。
オプション #2/#3 は、次のようにコメントアウトされています。
from PyQt4 import QtCore, QtGui
class MainWidget(QtGui.QDialog):
# Option #3 - Custom signal
closing = QtCore.pyqtSignal()
def __init__(self):
super(MainWidget, self).__init__()
self.layout = QtGui.QVBoxLayout(self)
for i in xrange(5):
label = ResourceLabel('label%02d' % i)
self.layout.addWidget(label)
# option #2
# Let a signal trigger the cleanup on the children
# self.destroyed.connect(label.close)
# option #3
# Use a custom signal emitted from the closeEvent,
# wired directly to the cleanup slot on the object
# self.closing.connect(label.close)
def closeEvent(self, event):
print "Closing main window"
# option #1
# if you want to trigger a cleanup specifically when
# this widget is closed, as opposed to destroyed
for i in xrange(self.layout.count()):
item = self.layout.itemAt(i)
widget = item.widget()
if widget:
try:
widget.close()
except:
pass
# Or Option #3 - emit a custom signal
self.closing.emit()
super(MainWidget, self).closeEvent(event)
class ResourceLabel(QtGui.QLabel):
def __init__(self, *args, **kwargs):
super(ResourceLabel, self).__init__(*args, **kwargs)
self.aResource = "FOO"
def close(self):
print "Cleaning up", self
self.aResource = None
if __name__ == "__main__":
app = QtGui.QApplication([])
win = MainWidget()
win.show()
win.raise_()
app.exec_()
どちらでも動作します。オプション #2 の方が気に入っています。これは、親ウィンドウがその子に少し依存せず、構築時に適切なウィンドウをクリーンアップするスロットに接続するだけだからです。
オプション #3 の理由は、以下のコメントに基づいています。あなたが投稿したコードでは、あなたのダイアログは実際にはまったく削除されていないと思います。それはまだ存在し、閉鎖されたばかりです。したがって、閉じるイベントはトリガーされますが、破棄シグナルはトリガーされません。したがって、オプション 3 は、カスタム シグナルを closeEvent に配置します。これは、destroyed
シグナルが削除された場合にシグナルが行う動作を正確に模倣します。