PyQT:区分close()函数和title-bar close [X]

PyQT: Differentiate between close() function and title-bar close [X]

我有以下功能询问用户是否真的要退出 window:

def closeEvent(self, event):
    if self.running:
        reply = QMessageBox.question(self, 'QUIT',
                                     'Calculations are currently running!\n'
                                     'Do you really want to quit?',
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
    else:
        return QMainWindow.closeEvent(self, event)

因此,当用户按下红色 X 时,将显示 QMessageBox。但是我仍然希望能够在没有 QMessageBox 的情况下终止 window,例如,如果我在代码中使用 close() 函数。是否有可能区分 CloseEvent 的不同发送者,例如 close() 函数或 X-Button?

您可以通过调用事件对象的spontaneous方法来区分系统事件和应用程序事件。因此,如果用户尝试通过单击 title-bar 关闭按钮或按 Alt+F4 来关闭 window , spontaneous() 方法将 return True.

这是一个简单的演示:

from PyQt5 import QtWidgets

class Window(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.button = QtWidgets.QPushButton('Close')
        self.button.clicked.connect(self.close)
        self.check = QtWidgets.QCheckBox('Running')
        self.check.toggled.connect(lambda x: setattr(self, 'running', x))
        self.check.setChecked(True)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.check)
        layout.addWidget(self.button)

    def closeEvent(self, event):
        if event.spontaneous():
            print('system close event')
            if self.running:
                reply = QtWidgets.QMessageBox.question(
                    self, 'QUIT',
                    'Calculations are currently running!\n'
                    'Do you really want to quit?',
                    QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                    QtWidgets.QMessageBox.No)
                if reply == QtWidgets.QMessageBox.Yes:
                    event.accept()
                else:
                    event.ignore()
        else:
            print('program close event')

if __name__ == '__main__':

    app = QtWidgets.QApplication(['Test'])
    window = Window()
    window.show()
    app.exec_()