如何在 PyQT 中检测父小部件关闭?

lia*_*dee 5 python qt pyqt

我创建了一个QVBoxLayout包含多个其他小部件的。QVBoxLayout当(当前是 a )的父窗口QDialog关闭时,我需要向所有小部件通知关闭事件,以便它们可以删除临时文件。这是惯用的吗?我该怎么做?

在我的应用程序中,我使用QLabel一个类进行子类化,该类允许我存储对构成 pixMap 的临时文件的引用。当它的父窗口关闭时,我需要能够关闭该文件。

编辑:我已经尝试处理关闭事件:

def closeEvent(self, event):
    self.imgFile.close()
Run Code Online (Sandbox Code Playgroud)

jdi*_*jdi 3

这里有几种方法可以实现这一点,使用我认为惯用的 Qt。

  1. 在父级上使用closeEvent直接对每个子级执行清理。
  2. 使用destroyed父级上的信号间接调用每个子级上的清理
  3. 从父级发出自定义信号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_()
Run Code Online (Sandbox Code Playgroud)

任何一个都会起作用。我更喜欢选项#2,因为它让父窗口对其子窗口保持一点不可知性,并且只需在构建时将正确的窗口连接到将清理它们的插槽。

选择#3 的原因是基于您下面的评论。在您发布的代码中,我的猜测是您的对话框根本没有真正被删除。它仍然存在并且刚刚被关闭。因此应该触发 close 事件而不是销毁信号。因此,选项 3 将一个自定义信号放入 closeEvent 中,该信号完全模仿destroyed信号被删除时会执行的操作。