Не удается закрыть приложение с графическим интерфейсом

#python #python-3.x #pyqt #pyqt5 #qwidget

#python #python-3.x #pyqt #pyqt5 #qwidget

Вопрос:

 from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(277, 244)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
        self.menubar.setObjectName("menubar")
        self.menuFile = QtWidgets.QMenu(self.menubar)
        self.menuFile.setObjectName("menuFile")
        MainWindow.setMenuBar(self.menubar)
        self.actionQuit = QtWidgets.QAction(MainWindow)
        self.actionQuit.setObjectName("actionQuit")
        self.actionQuit.setShortcut("Ctrl Q")
        self.actionQuit.setStatusTip("Quit the application")
        self.actionQuit.triggered.connect(MainWindow.closeEvent)
        self.menuFile.addAction(self.actionQuit)
        self.menubar.addAction(self.menuFile.menuAction())
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        MainWindow.show()

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menuFile.setTitle(_translate("MainWindow", "File"))
        self.actionQuit.setText(_translate("MainWindow", "Quit"))

class MyWindow(QtWidgets.QMainWindow):

    def closeEvent(self, event):
        print(event)
        result = QtWidgets.QMessageBox.question(self,
                      "Confirm Exit...",
                      "Are you sure you want to exit ?",
                      QtWidgets.QMessageBox.Yes| QtWidgets.QMessageBox.No)
        event.ignore()
        print(result)
        if result == QtWidgets.QMessageBox.Yes:
            event.accept()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = MyWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    sys.exit(app.exec_())
  

Когда я пытаюсь закрыть приложение с помощью сочетания клавиш Ctrl Q, появляется окно сообщения с вопросом, и когда я нажимаю на любой из вариантов, я получаю

 AttributeError: 'bool' object has no attribute 'ignore'
  

Где я ошибся?

Ответ №1:

Вы не должны напрямую вызывать closeEvent() метод (или методы, которые xxxEvent ), поскольку это вызывается внутренними элементами Qt через цикл событий, вместо этого вы должны использовать close() метод для косвенного вызова closeEvent() :

 from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(277, 244)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
        self.menubar.setObjectName("menubar")
        self.menuFile = QtWidgets.QMenu(self.menubar)
        self.menuFile.setObjectName("menuFile")
        MainWindow.setMenuBar(self.menubar)
        self.actionQuit = QtWidgets.QAction(MainWindow)
        self.actionQuit.setObjectName("actionQuit")
        self.actionQuit.setShortcut("Ctrl Q")
        self.actionQuit.setStatusTip("Quit the application")
        self.menuFile.addAction(self.actionQuit)
        self.menubar.addAction(self.menuFile.menuAction())
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menuFile.setTitle(_translate("MainWindow", "File"))
        self.actionQuit.setText(_translate("MainWindow", "Quit"))

class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyWindow, self).__init__(parent)
        self.setupUi(self)
        self.actionQuit.triggered.connect(self.close)

    def closeEvent(self, event):
        print(event)
        result = QtWidgets.QMessageBox.question(self,
                      "Confirm Exit...",
                      "Are you sure you want to exit ?",
                      QtWidgets.QMessageBox.Yes| QtWidgets.QMessageBox.No)
        event.ignore()
        print(result)
        if result == QtWidgets.QMessageBox.Yes:
            event.accept()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())
  

Ответ №2:

Подключив действие к функции подобным образом, self.actionQuit.triggered.connect(MainWindow.closeEvent)

вы гарантируете, что triggered сигнал передается в функцию, но этот сигнал является логическим значением, как написано в документации, что означает, что event является логическим значением в вашем коде ниже:

 def closeEvent(self, event):
    print(event)
    result = QtWidgets.QMessageBox.question(self,
                  "Confirm Exit...",
                  "Are you sure you want to exit ?",
                  QtWidgets.QMessageBox.Yes| QtWidgets.QMessageBox.No)
    event.ignore()
    print(result)
    if result == QtWidgets.QMessageBox.Yes:
        event.accept()
  

Логическое значение не имеет атрибута ignore or accept , отсюда и AttributeError. У меня нет решения, но это источник вашей проблемы. Надеюсь, выход из программы с помощью сочетания клавиш — это вопрос, на который уже был дан ответ.

Комментарии:

1. Спасибо за ваш ответ. Понял это с помощью инструкций print. Ищу, может ли кто-нибудь опубликовать какой-нибудь обходной путь.