PyQt5 closeEvent 方法

Posted

技术标签:

【中文标题】PyQt5 closeEvent 方法【英文标题】:PyQt5 closeEvent method 【发布时间】:2016-11-16 00:25:15 【问题描述】:

我目前正在学习如何使用 pyqt5 构建应用程序,但遇到了 closeEvent 方法的一些问题,已被覆盖,因此 QMessageBox 对象要求用户确认。它似乎与 X 按钮配合得很好——当操作被确认时,事件被“接受”,当点击取消按钮时,事件被“取消”。但是,当我从下拉文件菜单中使用退出按钮时,无论我单击哪个按钮,程序都会以退出代码 1 关闭。看起来很奇怪,因为我在两种情况下都使用相同的 closeEvent 方法。

import sys

from PyQt5.QtWidgets import QApplication, QMessageBox, QMainWindow, QAction


class window(QMainWindow):
    def __init__(self):

        super().__init__()

    def createUI(self):


        self.setGeometry(500, 300, 700, 700)

        self.setWindowTitle("window")


        quit = QAction("Quit", self)
        quit.triggered.connect(self.closeEvent)

        menubar = self.menuBar()
        fmenu = menubar.addMenu("File")
        fmenu.addAction(quit)

    def closeEvent(self, event):
        close = QMessageBox()
        close.setText("You sure?")
        close.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
        close = close.exec()

        if close == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

main = QApplication(sys.argv)
window = window()
window.createUI()
window.show()
sys.exit(main.exec_())

感谢您的建议!

【问题讨论】:

你是在控制台/终端中运行的吗?你有错误信息。 AttributeError: 'bool' object has no attribute 'accept' 当您单击按钮然后系统调用您的函数,但使用不同的 event 对象,该对象没有 accept()ignore(),因此您会收到错误消息并且程序以退出代码 1 结束。 【参考方案1】:

当您单击按钮时,程序会调用您的函数,但使用不同的 event 对象,该对象没有 accept()ignore(),因此您会收到错误消息并且程序以退出代码 1 结束。

您可以分配self.close,程序将使用正确的事件对象调用closeEvent()

quit.triggered.connect(self.close)

【讨论】:

在我的情况下,self.close 给出了AttributeErrorself.closeEvent 有效但不会触发closeEvent()【参考方案2】:

问题是接受是一种方法,而忽略只是一个属性。 这段代码对我有用:

def closeEvent(self, event):
            close = QtWidgets.QMessageBox.question(self,
                                         "QUIT",
                                         "Are you sure want to stop process?",
                                         QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
            if close == QtWidgets.QMessageBox.Yes:
                event.accept()
            else:
                event.ignore()

【讨论】:

此代码如何为您工作?您的代码中的“自我”指的是什么?在我的代码中,'self' 指的是 QMainWindow。你的代码对我不起作用。【参考方案3】:

我遇到了同样的问题,并通过 type-check-hack 进行了修复。这可能是一个丑陋的 hack,但它可以工作(在 macOS 10.15 上使用 python 3.8.0 和 PyQt 5.14.2 测试)。

class Gui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Gui, self).__init__()
        uic.loadUi("gui.ui", self)

        # ...

        self.actionExit = self.findChild(QtWidgets.QAction, "actionExit")
        self.actionExit.triggered.connect(self.closeEvent)

        # ...

    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Quit?',
                                     'Are you sure you want to quit?',
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            if not type(event) == bool:
                event.accept()
            else:
                sys.exit()
        else:
            if not type(event) == bool:
                event.ignore()

【讨论】:

【参考方案4】:
def exit_window(self, event):
    close = QtWidgets.QMessageBox.question(self,
                                           "QUIT?",
                                           "Are you sure want to STOP and EXIT?",
                                           QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
    if close == QtWidgets.QMessageBox.Yes:
        # event.accept()
        sys.exit()
    else:
        pass

【讨论】:

看完所有答案后,我决定做一个简单的改进。希望它可以帮助其他人将来面临同样的问题。谢谢大家。【参考方案5】:

如果您想从菜单中关闭 PyQt5 应用:

    当菜单事件触发调用时:self.MainWindow.close()(或者你要关闭什么窗口 在sys.exit(app.exec())之前添加此代码:self.MainWindow.closeEvent = lambda event:self.closeEvent(event) 当你真的想关闭调用event.accept()(可能还有return 1)并且如果你不想关闭窗口调用event.ignore()(不是event.reject()(它不适用于我))

【讨论】:

以上是关于PyQt5 closeEvent 方法的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖 closeEvent 函数以使其正常工作

关闭对话框后如何触发方法

pyqt添加确认框

PyQt 的 QMainWindow closeEvent 永远不会被调用

PyQt5.QThread 的 start() 方法不执行 run() 方法

mac 安装PyQt5