【问题标题】:Execute code when QWidget is actually destroyed, not just closed在 QWidget 实际被销毁时​​执行代码,而不仅仅是关闭
【发布时间】:2012-09-23 11:46:24
【问题描述】:

我创建了一个自定义 QDialog 类并覆盖了 closeEvent 以隐藏对话框,因为它是另一个小部件的子级。我的对话框只能在其父级关闭时关闭,而不是在它被接受、拒绝或用户单击关闭按钮时关闭。

这一切都很好,但现在我需要打开一个到数据库的连接,并且只有在对话框被销毁时才关闭它,而不仅仅是在它关闭时。

我的代码:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

def Log_Closed():
    print "Bye bye"

class My_dlg(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__( self, parent )

        #self.conn = open_connection()
        print "Connection Opened"

        close_btn  = QPushButton("Actually Close")
        QVBoxLayout(self).addWidget(close_btn)

        close_btn.clicked.connect(self.Actually_Close)
        self.destroyed.connect(Log_Closed)

    def Actually_Close(self):
        print "Actually Close"
        self.parent().close()

    def closeEvent(self, event):
        if event.type() == QEvent.Close:
            event.ignore()
            self.hide()
            print "hidden"

    # And I guess I need something like
    def destroyEvent(self, event):
        #self.conn.close()
        print "Connection Closed"
        event.accept()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main= QMainWindow()
    tsd = My_dlg(main)
    tsd.show()
    sys.exit(app.exec_())

有什么想法吗?

【问题讨论】:

  • 如果对话框只应在其父级关闭时关闭,为什么不直接使用父级的closeEvent 来执行必要的清理操作?
  • 我创建了一个小型 python 应用程序,它加载运行各种对话框的文件并使其保持动态,在其中一个子对话框中定义的所有内容都需要保留在那里。我不想关闭在父级的子级中打开的连接,因为这违背了我的设置目的。不过还是谢谢。

标签: python qt pyqt destroy


【解决方案1】:

要在QObject 被删除时接收通知,请连接到其destroyed(QObject*) 信号。

但是,在 Python 中,对象删除的可预测性不如 C++,因为对象是垃圾回收的。例如,在Python documentation 中查看与__del__() 相关的所有注意事项。程序退出时它们可能不会被删除,这可能是您没有收到信号的原因。

您可以显式管理数据库连接,而不是依赖删除对话框。在这个简单的示例中,您甚至可以使用 context manager 来获得更好的代码。


无论哪种方式,以下是您的代码版本,其行为符合您的预期:https://gist.github.com/3827718

我所做的更改是:

  • 设置app.setQuitOnLastWindowClosed 以确保在对话框关闭时应用程序不会退出。我认为这是您想要的行为,否则这个问题没有意义。

  • 在对话框上将Qt.WA_DeleteOnClose 设置为False,以防止它在关闭时自行删除。这比覆盖closeEvent 更好。

  • Actually_Close() 中,对话框会自行删除(这也会关闭它)。这会触发destroyed 信号。

使用此代码,当您单击按钮时,输出与您预期的一样:

Connection Opened
Actually Close
Bye bye

【讨论】:

  • 感谢您的回复。最初我也是这么想的,但我试过了,但它似乎没有做任何事情,所以我认为我做错了什么。无论如何,我已经更新了我的代码以包含被破坏的连接,但和以前一样,它似乎不起作用。你知道我做错了什么吗?
  • 对不起,我没有仔细阅读您的示例。因为 Python 使用垃圾回收,所以对象生命周期的行为比 C++ 中的更微妙。特别是,Python 不保证对象会在程序退出时被删除,所以我怀疑这就是这里发生的事情。我会试着澄清一下。
猜你喜欢
  • 2021-09-11
  • 1970-01-01
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-08
  • 2014-09-15
相关资源
最近更新 更多