为什么接受PyQt4 QDialog时closeEvent和destroyed槽不被调用?

1 投票
2 回答
4282 浏览
提问于 2025-04-16 15:13

问题标题里已经说得很清楚了,下面是我简化过的代码。根据文档的说明:http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qdialog.html#done,点击“确定”按钮时,窗口应该会关闭。实际上,如果我用窗口的关闭按钮来关闭它,确实会触发这个事件:

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

class MyDialog(QDialog):    
    def __init__(self):
        QDialog.__init__(self)
        self.button_box = QDialogButtonBox(self)
        self.button_box.addButton(self.button_box.Ok)
        self.connect(self.button_box, SIGNAL('accepted()'), self.on_accept)
        layout = QVBoxLayout()
        layout.addWidget(self.button_box)
        #self.setAttribute(Qt.WA_DeleteOnClose)
        self.setLayout(layout)
        self.connect(self.button_box, SIGNAL('destroyed(QObject*)'), self.on_destroyed)

    def on_destroyed(self, *args):
        print("destroying dialog")

    def on_accept(self):
        print("accepting")
        self.done(1)

    def closeEvent(self, event):
        print("close")
        return QDialog.closeEvent(self, event)

#    def __del__(self):
#        QDialog.destroy(self)

my_app = QApplication([])
my_widget = MyDialog()
result = my_widget.exec_()
del my_widget
#my_widget.destroy()
if result == 1:
    print("result!")
else:
    print("other result:", result)
my_app.exec_()

2 个回答

1

这跟文档上说的完全不一样:

就像QWidget.close()一样,如果设置了Qt.WA_DeleteOnClose这个标志,done()会在关闭对话框时删除它。

它不会触发关闭事件(本来就不应该触发 - 你是接受了对话框,而不是关闭它;这两者是不同的),而且你把负责删除对话框的那部分代码注释掉了。

3

这个答案来自于 http://www.riverbankcomputing.com/pipermail/pyqt/2011-April/029589.html,非常感谢汉斯-彼得·扬森。

  1. 不要把处理被销毁信号的函数挂到正在被销毁的对象上。(回头看这点似乎很明显)

  2. QDialog.accept() 不会触发 closeEvent,尽管它确实会被销毁——我觉得这是个bug,或者文档说明得不够清楚。

撰写回答