App crashes when using QWidgets.QMessageBox

Alon

So I've been trying my luck with PyQT5 to give a GUI to an app I've been working on.

I've encountered an issue with QMessageBox feature.

I've been trying to create an "Exit" Action on the MenuBar of the app. And at first I only made it exit when clicked and it worked.

Now I want to make it give a pop up message of "Are you sure?", which is exactly what the QMessageBox does. So this is my code now:

class Window(QtWidgets.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self.ui = uic.loadUi('rent_creation.ui', self)
        self.home()

    def home(self):
        self.ui.actionExit.triggered.connect(self.close_application)
        self.show()


    def close_application(self):
        choice = QMessageBox.question(self, 'Quit?',
                                      "Are you sure you want to quit?",
                                      QMessageBox.Yes | QMessageBox.No)
        if choice == QMessageBox.Yes:
            sys.exit()
        else:
            pass

Now every time I click on the Exit button when I run this code, The Python crashes. I'm not sure what I'm doing wrong... I've been looking around the internet and it all look well.... I've tried all the variation possible of passing QmessageBox (for example I tried adding QWidgets.QMessageBox.Yes/No and it didn't fix this issue).

I've been following a tutorial on the internet where This code is practically the same as his, and it works for him in the tutorial somehow.

Francesco Montesano

caveat: I am on linux, so things are likely a bit different.

However I wouldn't be surprised if the problem is related with the fact that you use sys.exit to quit the GUI. You probably should cleanly close the window, the QApplication and then exit the program.

The following example might solve your issue. Since I don't have you ui file, I just added a menu action to close the the window and connect it with the QMainWindow.close slot and then override the closeEvent method. See the comments in the code:

import sys
from PyQt5 import QtWidgets


class Window(QtWidgets.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self.home()

    def home(self):
        # add a menu bar with a File menu and a Close action
        menu_bar = QtWidgets.QMenuBar(self)
        menu = QtWidgets.QMenu('File', menu_bar)
        menu_bar.addMenu(menu)
        action = menu.addAction('Close')

        # connect the Close action with the QMainWindow.close slot
        action.triggered.connect(self.close)

        self.setMenuBar(menu_bar)

     def closeEvent(self, event):
        """override the QMainWindow.closeEvent method to:

        * fire up a QMessageBox with a question
        * accept the close event if the user click yes
        * ignore it otherwise.

        Parameters
        ----------
        event : QtCloseEvent
            emitted when someone or something asks to close the window
        """
        if self.ask_quit():
            event.accept()
        else:
            event.ignore()

    def ask_quit(self):
        choice = QtWidgets.QMessageBox.question(self, 'Quit?',
                        "Are you sure you want to quit?",
                        QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
        return choice == QtWidgets.QMessageBox.Yes


if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)

    w = Window()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple')
    w.show()

    sys.exit(app.exec_())

The above way of closing the window, i.e. using the closeEvent and connect the menu action to close, has the advantage that the confirmation box is opened every time someone asks to close the window, independently of the method: you get the message box also clicking on the window X button or with alt+F4


Edit: example of how to cleanly close the QApplication only from the Close menu. This should be more in line with the original behavior of the app in the question (see comment).

class Window(QtWidgets.QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self.home()

    def home(self):
        menu_bar = QtWidgets.QMenuBar(self)

        menu = QtWidgets.QMenu('File', menu_bar)
        menu_bar.addMenu(menu)

        action = menu.addAction('Close')
        # connect the Close menu to the ``ask_quit`` slot to ask and exit the
        # application on "yes"
        action.triggered.connect(self.ask_quit)

        self.setMenuBar(menu_bar)

    def closeEvent(self, event):
        """Ignore all ways of closing"""
        event.ignore()

    @QtCore.pyqtSlot()
    def ask_quit(self):
        choice = QtWidgets.QMessageBox.question(self, 'Quit?',
                        "Are you sure you want to quit?",
                        QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
        if choice == QtWidgets.QMessageBox.Yes:
            QtWidgets.QApplication.quit()

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related