Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Trying to use closeEvent on MainWindow if user press X



  • Hi,
    I am trying to code so that if the user clicks X on the main window frame to exit, it pops a message asking if he really wants to quit (could've been accidental).

    This is the piece of code I have for it:

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

    However, if I run that, nothing happens. I've seen some videos and their code looks like this:

    import sys
    from PyQt5.QtWidgets import (QApplication, QWidget, QMessageBox)
    
    class MainWindow(QWidget):
    	def __init__(self):
    		super().__init__()
    
    	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__':
    	app = QApplication(sys.argv)
    
    	demo = MainWindow()
    	demo.show()
    
    	sys.exit(app.exec_())
    

    What I dont understand here, is that he doesnt call closeEvent anywhere. I've seen other examples doing the same. They are all under

    class MainWindow(QWdiget):
    

    However, the only class I have on mine (after developing the UI on QTDesigner), is this one:

    class Ui_MyProgram(object):
    

    Can anyone help me? I am lost.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    That class you get from designer is meant to be combined with a widget. And in that widget you'll reimplement the closeEvent method.



  • Sorry, im rather new to everything. Should I add a QtWdigets to the class? I tried and it didnt work, returned an error:

    class Ui_Proofo(object, QtWidgets):
    

  • Lifetime Qt Champion

    No, please take a look at the Using Designer of the PyQt documentation.



  • @SGaist
    I read it but im not sure i understand what you meant.
    The class I get? I've only got one, and thats the one I showed in my snipped.


  • Lifetime Qt Champion

    @DouglinhasZN It is shown in the link @SGaist posted:

    from PyQt5.QtWidgets import QDialog
    from ui_imagedialog import Ui_ImageDialog # Your UI class from designer
    
    class ImageDialog(QDialog): # This is your own class
        def __init__(self):
            super(ImageDialog, self).__init__()
    
            # Set up the user interface from Designer.
            self.ui = Ui_ImageDialog() # Here you use the class from designer to create the UI
            self.ui.setupUi(self)
    


  • @jsulm I see, but I don't understand just by looking at that code, do you mind explaining abit further?
    This is all I have on my code:

    import sys
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtWidgets import QMessageBox
    import urllib3
    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    from urllib.parse import urlparse
    urllib3.disable_warnings()
    
    class Ui_Proofo(object):
        def setupUi(self, Proofo):
    

    Everything else are functions


  • Lifetime Qt Champion

    @DouglinhasZN said in Trying to use closeEvent on MainWindow if user press X:

    Ui_Proofo

    This is the UI class from designer. You can use it in your MainWindow class as shown before. What exactly is not clear?



  • I dont have a MainWindow class, unless that's Ui_Proofo.
    And if that's the case, it's already in there but it doesn't recognise it. I dont get an error or anything like that, it just doesnt do anything.


  • Lifetime Qt Champion

    @DouglinhasZN Can you please show how you're using Ui_Proofo? One usually does not use generated Ui_ classes directly as all manual changes in there will be lost next time the code is generated.



  • How I am using it? Im guessing you'd like the snippets for my code?

    import sys
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtWidgets import QMessageBox
    import urllib3
    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    from urllib.parse import urlparse
    urllib3.disable_warnings()
    
    
    class Ui_Proofo(object):
        def setupUi(self, Proofo):
        {Here is the UI, so all my labels, buttons, boxes etc.}
        def retranslateUi(self, Proofo):
    
    if __name__ == "__main__":
        import sys
        app = QtWidgets.QApplication(sys.argv)
        Proofo = QtWidgets.QMainWindow()
        ui = Ui_Proofo()
        ui.setupUi(Proofo)
        Proofo.show()
        sys.exit(app.exec_())
    

  • Lifetime Qt Champion

    @DouglinhasZN You should do it like described in the link above: create another class (call it for example MainWindow) and load your Ui_Proofo there as UI and then implement the close event in MainWindow.



  • Thank you @jsulm , I gave it a go:

    from CVE_Design import Ui_Proofo
    class MainWindow(QWidget):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.ui = Ui_Proofo() # Here you use the class from designer to create the UI
            self.ui.setupUi(self)
        def closeEvent(self, event):
                    close = QMessageBox.question(self, "QUIT", "Are you sure want to stop process?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
                    if close == QMessageBox.Yes:
                        event.accept()
                    else:
                        event.ignore()
    

    However, nothing seems to happen. I apologise if I seem to be overcomplicating it, but I really am clueless now.



  • @DouglinhasZN said in Trying to use closeEvent on MainWindow if user press X:

    However, nothing seems to happen.

    What does this mean? You get no UI appear when you run the program, MainWindow.__init__() is not called, , or you don't get the close message box when you try to close the widget? Do yourself a favor and at least put in a couple of print() statements so you know what is being executed.



  • @JonB I had some print statement, but they dont get printed. The code itself don't seem to run. When I close the application, nothing happens, it just closes as it normally would



  • @DouglinhasZN
    Nothing shown in your post above is going to run if you never create an instance of MainWindow. You only show that fragment of your code, not where you create it from, so who knows.



  • @JonB said in Trying to use closeEvent on MainWindow if user press X:

    your post above is going to run if you never create an instance of MainWindow.

    What do you mean where I create it from?
    @JonB



  • @JonB I see where you are coming from, you mean adding the following under: if name == "main":

    w = MainWindow()
    w.setupUi(MainWindow)
    

    ?
    I have tried that and indeed it does work, but it creates a new application. In that application it does everything I want it to, but its not my main one



  • @DouglinhasZN
    I'm sorry, I really don't understand. There is no "new application"! I suspect you mean a new, separate window, which is kind of what I was wondering....

    We have seen your latest class MainWindow(QWidget): definition. Can you now paste the whole of your code from

    if __name__ == "__main__":
    

    downward and then we might see what is going on. The trouble is we keep seeing snippets....



  • @DouglinhasZN

    Hello!

    You can try my code, it should intercept the close event:

    class UI_MainWindow(QMainWindow):
        def __init__(self):
            super(UI_MainWindow, self).__init__()
            print("Initialization succeeded")
    
        def closeEvent(self, event):
            print("closeEvent has been called")
            userResult = QMessageBox.question(None, "Quit", "Do you want to close the program?", QMessageBox.Yes, QMessageBox.No)
    
            if userResult == QMessageBox.Yes:
                event.accept()
            else:
                event.ignore()
    


  • @JonB I see, I have posted the whole of my code up in the thread, but here it is:

    import sys
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtWidgets import QMessageBox
    import urllib3
    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    from urllib.parse import urlparse
    urllib3.disable_warnings()
    
    
    class Ui_Proofo(object):
        def setupUi(self, Proofo):
        {Here is the UI, so all my labels, buttons, boxes etc.}
        def retranslateUi(self, Proofo):
    
    from CVE_Design import Ui_Proofo
    class MainWindow(QWidget):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.ui = Ui_Proofo()
            self.ui.setupUi(self)
    
        def closeEvent(self, event):
                    close = QMessageBox.question(self, "QUIT", "Are you sure want to stop process?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
                    print("okay this is done 2")
                    if close == QMessageBox.Yes:
                        print("okay this is done 3")
                        event.accept()
                    else:
                        event.ignore()
    
    if __name__ == "__main__":
        import sys
        app = QtWidgets.QApplication(sys.argv)
        Proofo = QtWidgets.QMainWindow()
        ui = Ui_Proofo()
        ui.setupUi(Proofo)
        Proofo.show()
        sys.exit(app.exec_())
    


  • @DouglinhasZN

    So, what happens when you press X on the MainWindow?



  • @DouglinhasZN
    You have written a new class MainWindow with the closeEvent() in it, but you never create/use MainWindow anywhere in your code, do you? That's why it has no effect.

    Proofo = QtWidgets.QMainWindow() still creates it as QMainWindow. You need to create it as a MainWindow to use the code shown.

    Sorry, I haven't any more time right now, hopefully someone will show what you're supposed to do. Hopefully it's just

    Proofo = MainWindow()
    

    And I think you want to get rid of your

        ui = Ui_Proofo()
        ui.setupUi(Proofo)
    

    because MainWindow.__init__() is doing that bit. So:

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


  • @Cobra91151 Nothing happens, its almost as if its not linking that class to the overall GUI.
    Instead, if I add

    w = MainWindow()
    w.setupUi(MainWindow)
    

    Then it will load up a new window as well as the main window. On that new window, the code will work fine

    @JonB I hear what you're saying, I had similar code to what you've suggested but I ran with your suggestion and it opens up a new blank window rather than my Ui from Qt Designer (Proofo)


  • Lifetime Qt Champion

    @DouglinhasZN said in Trying to use closeEvent on MainWindow if user press X:

    w = MainWindow()
    w.setupUi(MainWindow)

    That code does not make sense.

    Straight from the documentation I linked:

    import sys
    from PyQt5.QtWidgets import QApplication, QDialog
    from ui_imagedialog import Ui_ImageDialog << The file generated from your .ui file
    
    app = QApplication(sys.argv)
    window = QDialog() << a widget
    ui = Ui_ImageDialog() << instance of the generated class
    ui.setupUi(window) << the parameter of setupUi must be an instance of a QWidget based class. In this case QDialog.
    
    window.show()
    sys.exit(app.exec_())
    

Log in to reply