Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Language Bindings
  4. closeEvent not working
Forum Updated to NodeBB v4.3 + New Features

closeEvent not working

Scheduled Pinned Locked Moved Unsolved Language Bindings
32 Posts 8 Posters 20.0k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • JonBJ JonB

    @ZioLupo I'm an old C programmer shocked by the ugliness of python!!

    ewerybodyE Offline
    ewerybodyE Offline
    ewerybody
    wrote on last edited by
    #16

    @ZioLupo what Python version are you using?
    I currently have no problems with 3.6.5 + PySide2 but my apps never close on the latest Python 3.7.

    1 Reply Last reply
    0
    • Z ZioLupo

      @SGaist
      As far as I know pyuic is not included in PySide2.

      Regarding setting the loaded widget as central widget I will investigate

      ewerybodyE Offline
      ewerybodyE Offline
      ewerybody
      wrote on last edited by
      #17

      @ZioLupo said in closeEvent not working:

      As far as I know pyuic is not included in PySide2.

      its pyside2uic!
      I do from pyside2uic import compileUi , compile my ui-files whenever changed. and do:

          self.ui = compiled_ui.Ui_Form()
          self.ui.setupUi(self.some_main_widget)
      
      Z 1 Reply Last reply
      0
      • SaelythS Offline
        SaelythS Offline
        Saelyth
        wrote on last edited by Saelyth
        #18

        I was porting my code of a working program from PyQt5 to PySide2 and found the same issue:

        def closeEvent(self, event):
            """Write window size and position to config file"""
            ini_options.setValue("menu_size", self.ui.size())
            ini_options.setValue("menu_position", self.ui.pos())
            event.accept()
        
        def eventFilter(self, target, event):
            print(event.type())
        

        I am using two Tabs and this was the result of me playing with the tabs. These are the only events printed:

        PySide2.QtCore.QEvent.Type.PolishRequest
        PySide2.QtCore.QEvent.Type.Move
        PySide2.QtCore.QEvent.Type.Resize
        PySide2.QtCore.QEvent.Type.Show
        PySide2.QtCore.QEvent.Type.ShowToParent
        PySide2.QtCore.QEvent.Type.UpdateLater
        PySide2.QtCore.QEvent.Type.Paint
        PySide2.QtCore.QEvent.Type.WindowDeactivate
        PySide2.QtCore.QEvent.Type.Hide
        

        closeEvent is never printed when I close the window. Shouldn't be somewhere after WindowDeactivate and before Hide?

        If I just open the software and close it without playing with the tabs, them the events are:

        PySide2.QtCore.QEvent.Type.PolishRequest
        PySide2.QtCore.QEvent.Type.Destroy
        

        I don't get why Destroy doesn't appears if I just switch to one tab to another (on the same MainWindow widget). Is the eventFilter bugged and it doesn't receives all the events?

        Z 1 Reply Last reply
        0
        • ewerybodyE ewerybody

          @ZioLupo said in closeEvent not working:

          As far as I know pyuic is not included in PySide2.

          its pyside2uic!
          I do from pyside2uic import compileUi , compile my ui-files whenever changed. and do:

              self.ui = compiled_ui.Ui_Form()
              self.ui.setupUi(self.some_main_widget)
          
          Z Offline
          Z Offline
          ZioLupo
          wrote on last edited by
          #19

          @ewerybody
          As I wrote some message after, yes there is -of course - pyside2-uic!
          But I don't like to use it.
          Using it solve all of my problems because it produce a class and with the class I can do what I want (inheriting from it, for example).

          But I would like to avoid to use it

          ewerybodyE 1 Reply Last reply
          0
          • SaelythS Saelyth

            I was porting my code of a working program from PyQt5 to PySide2 and found the same issue:

            def closeEvent(self, event):
                """Write window size and position to config file"""
                ini_options.setValue("menu_size", self.ui.size())
                ini_options.setValue("menu_position", self.ui.pos())
                event.accept()
            
            def eventFilter(self, target, event):
                print(event.type())
            

            I am using two Tabs and this was the result of me playing with the tabs. These are the only events printed:

            PySide2.QtCore.QEvent.Type.PolishRequest
            PySide2.QtCore.QEvent.Type.Move
            PySide2.QtCore.QEvent.Type.Resize
            PySide2.QtCore.QEvent.Type.Show
            PySide2.QtCore.QEvent.Type.ShowToParent
            PySide2.QtCore.QEvent.Type.UpdateLater
            PySide2.QtCore.QEvent.Type.Paint
            PySide2.QtCore.QEvent.Type.WindowDeactivate
            PySide2.QtCore.QEvent.Type.Hide
            

            closeEvent is never printed when I close the window. Shouldn't be somewhere after WindowDeactivate and before Hide?

            If I just open the software and close it without playing with the tabs, them the events are:

            PySide2.QtCore.QEvent.Type.PolishRequest
            PySide2.QtCore.QEvent.Type.Destroy
            

            I don't get why Destroy doesn't appears if I just switch to one tab to another (on the same MainWindow widget). Is the eventFilter bugged and it doesn't receives all the events?

            Z Offline
            Z Offline
            ZioLupo
            wrote on last edited by
            #20

            @Saelyth
            I think that we really have the same issue.
            AN issue that can be a wrong interpretation of how QtUiTools.QUiLoader().load works.
            It is returning an instance, not a class as.
            In this way we have two QMainWindow nested one in the other.
            With this workaround it worked:

                def __init__(self, ui_file, parent=None):
                    super(Form, self).__init__(parent)
                    self.ui=QtUiTools.QUiLoader().load(ui_file)
                    self.setCentralWidget(self.ui)
            

            But you loose the geometry of the QMainWindow designed with Designer (and maybe something more but I don't have the skill for investigating further)

            We should find a way to modify the inner closeEvent method but I don't know how to do it.
            Moreover I don't like to have two QMainWindow.

            Of course if someone has a real working sample code of a QMainWindow designed in Designer and then correctly loaded and used as a class... it would be really appreciated

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #21

              Then remove your Form class as it's not useful in your case.

              You can then create a custom event filter object that should handle the close event and whatever you want to do in it.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • SaelythS Offline
                SaelythS Offline
                Saelyth
                wrote on last edited by Saelyth
                #22

                With the original @ZioLupo code the override of eventFilter would works just fine, but closeEvent wouldn't (that was the issue).

                class Form(QtWidgets.QMainWindow):
                    def __init__(self):
                        super().__init__()
                        self.ui = QUiLoader().load("myfile.ui")
                        self.ui.buttonLoad.clicked.connect(self.load_something)
                
                    def eventFilter(self, target, event):
                        print("this works")
                        return False
                
                    def closeEvent(self, event):
                        print("this doesn't works")
                

                But that creates two QWidgets (one for the Form class and one for self.ui). if I understood you right, @Sgaist, you suggest to make the Form class a non-QWidget, as the Qwidget will be load into self.ui, right? But then, if the Form class is not a QWidget, I don't get how to set the closeEvent or eventFilter methods for the self.ui QWidget.

                I tried to do what you suggest with my next code. The windows open just fine but no override works and no events get to my handlers.

                class Form(object):
                    def __init__(self):
                        super().__init__()
                        self.ui = QUiLoader().load("myfile.ui")
                        self.ui.eventFilter = self.eventFilter
                        self.ui.closeEvent = self.closeEvent
                
                    def eventFilter(self, target, event):
                        print("doesn't works")
                        return False
                
                    def closeEvent(self, event):
                        print("doesn't works")
                

                I think the issue here is that we were waiting for PySide2 while we were working temporary on PyQt5, and assumed that PySide2 would behave like PyQt5, where we would port our Qt Designer UI to .py with pyuic command. But when PySide2 was released, we saw an alternative way to do things (load the .ui file directly) and now we are trying to skip one of the step (it seems unnecesary to convert the .ui file to .py in PySide2 if we can directly load the .ui file). However, while trying to do that, we got lost in the process as we lost something which we were familiar with: the abbility to override the UI events.

                A working example on how to load a .ui file with PySide2 where closeEvent works would help us a lot.

                JonBJ 1 Reply Last reply
                0
                • Z ZioLupo

                  @ewerybody
                  As I wrote some message after, yes there is -of course - pyside2-uic!
                  But I don't like to use it.
                  Using it solve all of my problems because it produce a class and with the class I can do what I want (inheriting from it, for example).

                  But I would like to avoid to use it

                  ewerybodyE Offline
                  ewerybodyE Offline
                  ewerybody
                  wrote on last edited by
                  #23

                  @ZioLupo said in closeEvent not working:

                  @ewerybody
                  As I wrote some message after, yes there is -of course - pyside2-uic!

                  Sorry. I didn't see you writing this.
                  What I just meant is that the name is NOT pyside2-uic (with a dash) but pyside2uic without the dash!

                  But I don't like to use it.
                  Using it solve all of my problems because it produce a class and with the class I can do what I want (inheriting from it, for example).

                  But I would like to avoid to use it

                  I would always avoid loading ui files directly and compile them only when changed. This way you can easily debug/step through the code. You see the generated structure and you can learn how UIs are written and you can strip a release of the ui files in the end.

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #24

                    Just one thing: you are not using eventFilter correctly, you don't install it.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    1
                    • SaelythS Saelyth

                      With the original @ZioLupo code the override of eventFilter would works just fine, but closeEvent wouldn't (that was the issue).

                      class Form(QtWidgets.QMainWindow):
                          def __init__(self):
                              super().__init__()
                              self.ui = QUiLoader().load("myfile.ui")
                              self.ui.buttonLoad.clicked.connect(self.load_something)
                      
                          def eventFilter(self, target, event):
                              print("this works")
                              return False
                      
                          def closeEvent(self, event):
                              print("this doesn't works")
                      

                      But that creates two QWidgets (one for the Form class and one for self.ui). if I understood you right, @Sgaist, you suggest to make the Form class a non-QWidget, as the Qwidget will be load into self.ui, right? But then, if the Form class is not a QWidget, I don't get how to set the closeEvent or eventFilter methods for the self.ui QWidget.

                      I tried to do what you suggest with my next code. The windows open just fine but no override works and no events get to my handlers.

                      class Form(object):
                          def __init__(self):
                              super().__init__()
                              self.ui = QUiLoader().load("myfile.ui")
                              self.ui.eventFilter = self.eventFilter
                              self.ui.closeEvent = self.closeEvent
                      
                          def eventFilter(self, target, event):
                              print("doesn't works")
                              return False
                      
                          def closeEvent(self, event):
                              print("doesn't works")
                      

                      I think the issue here is that we were waiting for PySide2 while we were working temporary on PyQt5, and assumed that PySide2 would behave like PyQt5, where we would port our Qt Designer UI to .py with pyuic command. But when PySide2 was released, we saw an alternative way to do things (load the .ui file directly) and now we are trying to skip one of the step (it seems unnecesary to convert the .ui file to .py in PySide2 if we can directly load the .ui file). However, while trying to do that, we got lost in the process as we lost something which we were familiar with: the abbility to override the UI events.

                      A working example on how to load a .ui file with PySide2 where closeEvent works would help us a lot.

                      JonBJ Online
                      JonBJ Online
                      JonB
                      wrote on last edited by JonB
                      #25

                      @Saelyth
                      As per what @SGaist has written, in my PyQt like yours (my page class is derived from QWidget) the __init__() ends with line:

                          self.window().installEventFilter(self)
                      

                      and my event handlers (eventFilter()) work.

                      SaelythS 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @Saelyth
                        As per what @SGaist has written, in my PyQt like yours (my page class is derived from QWidget) the __init__() ends with line:

                            self.window().installEventFilter(self)
                        

                        and my event handlers (eventFilter()) work.

                        SaelythS Offline
                        SaelythS Offline
                        Saelyth
                        wrote on last edited by Saelyth
                        #26

                        @JonB On PyQt and PyQt5 it works (I've been using it that way) but on Pyside2 it doesn't. Note that I was installing the filters (I just forgot to type it in my previous message). Anyway I ended up using pyside2-uic (with a dash) to make my code safer to this issues.

                        1 Reply Last reply
                        1
                        • Z ZioLupo

                          @SGaist , my code was a workaround to another problem.
                          If you do what you suggested (it was my first choice), the windows will be empty, no widgets will appear.
                          It works if you define the widgets one by one inside the code, but if you are loading them with QtUiTools is not working.
                          A mistery for me.

                          Thats why i changed the code. I can put the call to show() in the main but calling "ui": form.ui.show().
                          THis is working but closeEvent is not reachable.

                          I'm attaching two pictures where you can see both codes and results.
                          One is showing the widgets but closeEvent is not working, the other is not showing the widgets but closeEvent is working.

                          Thank for your help
                          0_1530686378193_closeEvent KO.png
                          0_1530686392696_empty.png

                          L Offline
                          L Offline
                          L.Giuliano
                          wrote on last edited by
                          #27

                          @ZioLupo As the content was loaded to self.ui, it's necessary to use form.ui.show() instead of form.show().

                          1 Reply Last reply
                          0
                          • L Offline
                            L Offline
                            L.Giuliano
                            wrote on last edited by
                            #28
                            This post is deleted!
                            1 Reply Last reply
                            0
                            • S Offline
                              S Offline
                              sylvalas
                              wrote on last edited by
                              #29

                              is this thing solved?
                              it's 2021 almost 2022 now.
                              PySide6 still has the same issue I think.
                              as far as I know, with pyside6.QtUiTools.QUiLoader(), you can only load ui to an attribute of a shell class e.g. "self.ui" instead of to "self"
                              which causes some trouble triggering the modified closeEvent method.

                              The type of "self.ui" will still be QMainWindow(depends on what u use). I tried to override closeEvent() but it still won't work that's what confuses me.

                              Why cant they just add some method to let us load widgets to "self" -_- like "uic.loauUi()" in pyqt

                              H 1 Reply Last reply
                              0
                              • S sylvalas

                                is this thing solved?
                                it's 2021 almost 2022 now.
                                PySide6 still has the same issue I think.
                                as far as I know, with pyside6.QtUiTools.QUiLoader(), you can only load ui to an attribute of a shell class e.g. "self.ui" instead of to "self"
                                which causes some trouble triggering the modified closeEvent method.

                                The type of "self.ui" will still be QMainWindow(depends on what u use). I tried to override closeEvent() but it still won't work that's what confuses me.

                                Why cant they just add some method to let us load widgets to "self" -_- like "uic.loauUi()" in pyqt

                                H Offline
                                H Offline
                                HLsms
                                wrote on last edited by
                                #30

                                @sylvalas Still not solved by the looks of it, at least for me on pyside6, same issue if you load in the ui file (which I want to rather than compile).

                                However, a workaround exists (https://stackoverflow.com/questions/14834494/pyqt-clicking-x-doesnt-trigger-closeevent), which is to place:

                                app.aboutToQuit.connect(self.closeEvent)
                                

                                inside the mainwindow class ( init or another func called when setting up the MW). This is kind of a cheat, as it is not capturing the close event, just the signal that it is about to close, so you cannot decline the event and stop the close. But functionally for me at least it is good enough to allow me to end other processes, safely disconnect hardware and tidy up before the close itself.

                                JonBJ 1 Reply Last reply
                                0
                                • H HLsms

                                  @sylvalas Still not solved by the looks of it, at least for me on pyside6, same issue if you load in the ui file (which I want to rather than compile).

                                  However, a workaround exists (https://stackoverflow.com/questions/14834494/pyqt-clicking-x-doesnt-trigger-closeevent), which is to place:

                                  app.aboutToQuit.connect(self.closeEvent)
                                  

                                  inside the mainwindow class ( init or another func called when setting up the MW). This is kind of a cheat, as it is not capturing the close event, just the signal that it is about to close, so you cannot decline the event and stop the close. But functionally for me at least it is good enough to allow me to end other processes, safely disconnect hardware and tidy up before the close itself.

                                  JonBJ Online
                                  JonBJ Online
                                  JonB
                                  wrote on last edited by
                                  #31

                                  @HLsms
                                  Completely untested, but because you are Python can't you monkey-patch self.ui.closeEvent = self.closeEvent?

                                  H 1 Reply Last reply
                                  0
                                  • JonBJ JonB

                                    @HLsms
                                    Completely untested, but because you are Python can't you monkey-patch self.ui.closeEvent = self.closeEvent?

                                    H Offline
                                    H Offline
                                    HLsms
                                    wrote on last edited by
                                    #32

                                    @JonB Yeah I used to do that, and it worked fine on PyQt5, but unfortunately it doesn't work at all on pyside6 (ditto pyside2 based on past discussion).

                                    1 Reply Last reply
                                    1

                                    • Login

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • Users
                                    • Groups
                                    • Search
                                    • Get Qt Extensions
                                    • Unsolved