Search code examples
pythonpyqtpyqt5qt-designerqdialog

Close Event are not called Keyboard Event and MessageBox


I programming with QT Designer a GUI and would like disable the Close Event with ESC-Key. The User has the possibility to close the Application with X on the top but not with any Keys.

The Function closeEvent(self,event) are not working.

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()

The function are on my main class: class Ui_Tool(object)

class Ui_LabelTool(object):
def setupUi(self, LabelTool):
    Tool.setObjectName("Tool")
    Tool.resize(650, 569)
    Tool.setMinimumSize(QtCore.QSize(650, 569))
    Tool.setMaximumSize(QtCore.QSize(650, 569))
    Tool.setAutoFillBackground(False)
    Tool.setSizeGripEnabled(False)
    ...

    #Events for Buttons
    self.SelectFolder.clicked.connect(self.setfolder)   
    self.SelectOutputFolder.clicked.connect(self.SetOutputFolder)       
    self.LoadeMeasurement.clicked.connect(self.LoadRecording)           
    self.StartButton.clicked.connect(self.startProcessing)              
    self.Next_btn.clicked.connect(self.nextOperation)                   
    self.Prev_Btn.clicked.connect(self.prefOperation)                   
    self.Reset_btn.clicked.connect(self.resetApp)

    self.treeView.clicked.connect(self.ClickMeasurement) 
    self.treeWidget.clicked.connect(self.CheckTopicSelect)              

    self.horizontalSlider.valueChanged.connect(self.SliderValueChange)
    self.horizontalSlider.sliderMoved.connect(self.dispSlider)

    self.BBObject_btn.clicked.connect(self.CreateBBObj)
    self.BBNoObject_btn.clicked.connect(self.CreateBBNoObj)

    self.ShowAll_btn.clicked.connect(self.SaveImages)

def retranslateUi(self, LabelTool):
    _translate = QtCore.QCoreApplication.translate
    Tool.setWindowTitle(_translate("Tool", "Tool"))
    self.LoadeMeasurement.setText(_translate("Tool", "Load Measurement"))
    self.StartButton.setText(_translate("Tool", "Start "))
    self.Reset_btn.setText(_translate("Tool", "Reset"))
    self.Header_lbl.setText(_translate("Tool", "Test"))
    ...

And this is my main Function:

if __name__ == "__main__":

    import sys
    app = QtWidgets.QApplication(sys.argv)
    Tool = QtWidgets.QDialog()
    ui = Ui_Tool()
    ui.setupUi(Tool)
    Tool.show()
    sys.exit(app.exec_())

What I do wrong?

I add the following class:

class Logic(QMainWindow, Ui_Tool):
def __init__(self, *args, **kwargs):
    QMainWindow.__init__(self, *args, **kwargs)
    self.setupUi(self)

def closeEvent(self, event):
    answer = QtWidgets.QMessageBox.question(
        self,
        'Are you sure you want to quit ?',
        'Task is in progress !',
        QtWidgets.QMessageBox.Yes,
        QtWidgets.QMessageBox.No)
    if answer == QtWidgets.QMessageBox.Yes:
        event.accept()
    else:
        event.ignore()

Solution

  • If the docs is reviewed:

    Escape Key

    If the user presses the Esc key in a dialog, QDialog::reject() will be called. This will cause the window to close: The close event cannot be ignored.

    So there are 2 possible solutions:

    1. Override keyPressEvent() method, when you press the escape key, call close().

    2. Override reject() method to make the verification of the QMessageBox and according to it make its logic.

    In addition to this implementation you must do it in the widget and not in the class generated by Qt Designer(1), considering the above the implementations of both solutions are:

    1.

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_LabelTool(object):
        def setupUi(self, Tool):
            Tool.setObjectName("Tool")
            Tool.resize(650, 569)
            Tool.setMinimumSize(QtCore.QSize(650, 569))
            Tool.setMaximumSize(QtCore.QSize(650, 569))
            Tool.setAutoFillBackground(False)
            Tool.setSizeGripEnabled(False)
            # ....
    
    
    class LabelTool(QtWidgets.QDialog, Ui_LabelTool):
        def __init__(self, parent=None):
            super(LabelTool, self).__init__(parent)
            self.setupUi(self)
    
        def verify_by_user(self):
            answer = QtWidgets.QMessageBox.question(
                self,
                "Are you sure you want to quit ?",
                "Task is in progress !",
                QtWidgets.QMessageBox.Yes,
                QtWidgets.QMessageBox.No,
            )
            return answer == QtWidgets.QMessageBox.Yes
    
        def keyPressEvent(self, event):
            if event.key() == QtCore.Qt.Key_Escape:
                self.close()
            else:
                super(LabelTool, self).keyPressEvent(event)
    
        def closeEvent(self, event):
            if self.verify_by_user():
                event.accept()
            else:
                event.ignore()
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = LabelTool()
        w.show()
        sys.exit(app.exec_())
    

    2.

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_LabelTool(object):
        def setupUi(self, Tool):
            Tool.setObjectName("Tool")
            Tool.resize(650, 569)
            Tool.setMinimumSize(QtCore.QSize(650, 569))
            Tool.setMaximumSize(QtCore.QSize(650, 569))
            Tool.setAutoFillBackground(False)
            Tool.setSizeGripEnabled(False)
            # ....
    
    
    class LabelTool(QtWidgets.QDialog, Ui_LabelTool):
        def __init__(self, parent=None):
            super(LabelTool, self).__init__(parent)
            self.setupUi(self)
    
        def verify_by_user(self):
            answer = QtWidgets.QMessageBox.question(
                self,
                "Are you sure you want to quit ?",
                "Task is in progress !",
                QtWidgets.QMessageBox.Yes,
                QtWidgets.QMessageBox.No,
            )
            return answer == QtWidgets.QMessageBox.Yes
    
        def reject(self):
            if self.verify_by_user():
                super(LabelTool, self).reject()
    
        def closeEvent(self, event):
            if self.verify_by_user():
                event.accept()
            else:
                event.ignore()
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = LabelTool()
        w.show()
        sys.exit(app.exec_())
    

    (1) Using the Generated Code