Skip to main content
 首页 » 编程设计

python之在 QWidget 实际被销毁时执行代码,而不仅仅是关闭

2025年05月04日11mfryf

我已经创建了一个自定义的 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_()) 

有什么想法吗?

请您参考如下方法:

要在删除 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