Search code examples
pythonpyqt5qt-designer

popup closeEvent code with code from QtDesigner


I'm trying to create a pop up message box when the "close" button is pressed. my code looks like as follow:


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMessageBox


class Ui_Form(object):
    def __init__(self):
        super().__init__()
        self.stop_request_1 = False
        self.stop_request_2 = False

    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 180)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
        Form.setSizePolicy(sizePolicy)
        Form.setMinimumSize(QtCore.QSize(400, 180))
        Form.setMaximumSize(QtCore.QSize(400, 180))

        self.btn_1 = QtWidgets.QPushButton(Form)
        self.btn_1.setGeometry(QtCore.QRect(30, 60, 86, 26))
        self.btn_1.setIconSize(QtCore.QSize(20, 20))
        self.btn_1.setObjectName("btn_1")

        self.btn_2 = QtWidgets.QPushButton(Form)
        self.btn_2.setGeometry(QtCore.QRect(250, 60, 86, 26))
        self.btn_2.setObjectName("btn_2")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.btn_1.setText(_translate("Form", "btn 1"))
        self.btn_2.setText(_translate("Form", "btn 2"))

    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Window Close', 'Are you sure you want to close the window?',
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
            print('Window closed')
        else:
            event.ignore()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

But when I run press the close button, "X", the popup window doesnt work.

The window just closes.

Do you guys know what can be wrong ?


Solution

  • You've got yourself into one of the most common mistakes of PyQt: you're editing the file generated by the pyuic utility.
    Those files are not intended for a starting point to begin your program with, but they always have to be used as imported modules. I suggest you to carefully read the documentation about using Designer.

    Now, to the problem at hand: closeEvent() is a member of the QWidget class, and is called by the QWidget instance when it is going to be closed. In your case, it will never be called, since you've made it a member of the Ui_Form class.

    First of all, rebuild the ui using pyuic. Then create a new script (which will be your main script of your program) and, following the third method specified in the designer documentation given above (the multiple inheritance approach), you create a subclass of QWidget for your widget, then finally override the closeEvent there:

    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtWidgets import QMessageBox
    from ui_form import Ui_Form
    
    class MyWidget(QtWidgets.QWidget, Ui_Form):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.setupUi(self)
    
        def closeEvent(self, event):
            reply = QMessageBox.question(self, 'Window Close', 
                'Are you sure you want to close the window?',
                QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
    
            if reply == QMessageBox.Yes:
                event.accept()
                print('Window closed')
            else:
                event.ignore()
    
    
    if __name__ == "__main__":
        import sys
        app = QtWidgets.QApplication(sys.argv)
        myWidget = MyWidget()
        myWidget.show()
        sys.exit(app.exec_())
    

    Remember: never, never edit the files generated by pyuic.