Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Problem with window close/closeEvent

Problem with window close/closeEvent

Scheduled Pinned Locked Moved Solved General and Desktop
close programcloseevent
5 Posts 2 Posters 22.2k Views
  • 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.
  • J Offline
    J Offline
    JonB
    wrote on 22 Sept 2017, 14:58 last edited by
    #1

    I am failing to get a Quit button to behave just like clicking on the "window close" "X" icon.

    There is a bit of precise detail below, but the problem ought really to be simple.

    I have inherited a large body of Qt5/PyQt5 code. It is possible I am failing to spot something relevant, but I see the outline as:

    class Main(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
    
            self.actionQuit = QtWidgets.QAction("Quit", self)
            self.actionQuit.triggered.connect(QtWidgets.QApplication.quit)
    
            self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
    
        def closeEvent(self, event):
            QSettings.setValue("main_geometry", self.saveGeometry())
            QSettings.setValue("main_state", self.saveState())
    
    
    if __name__ == '__main__':
        main = Main()
        sys.exit(app.exec_())
    

    As that stands, when I close the main window via the "X" close-icon it does call closeEvent() to save state. However, when Quit button is clicked the QtWidgets.QApplication.quit does not invoke closeEvent().

    So having looked at posts like:

    • https://forum.qt.io/topic/39699/solved-why-qdialog-does-not-receive-a-closeevent-on-hitting-esc/3
    • https://stackoverflow.com/questions/25191954/using-the-closeevent-in-a-qt-application-does-not-close-it
    • https://stackoverflow.com/questions/22460003/pyqts-qmainwindow-closeevent-is-never-called
    • http://www.qtcentre.org/archive/index.php/t-61003.html

    I changed code to self.actionQuit.triggered.connect(self.close), expecting that to work. However, that did not call closeEvent() before exiting.

    On a whim I commented out self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True), then not only is closeEvent() not called but the window/application does not close/quit/exit either. So now I don't really understand what connecting the button to self.close is doing anyway...

    • Should self.actionQuit.triggered.connect(self.close) be all I have to do/work?
    • Why does it not work for me? Am I omitting some important detail I am not aware of?
    K 1 Reply Last reply 22 Sept 2017, 15:47
    0
    • J JonB
      22 Sept 2017, 14:58

      I am failing to get a Quit button to behave just like clicking on the "window close" "X" icon.

      There is a bit of precise detail below, but the problem ought really to be simple.

      I have inherited a large body of Qt5/PyQt5 code. It is possible I am failing to spot something relevant, but I see the outline as:

      class Main(QtWidgets.QMainWindow):
          def __init__(self):
              super().__init__()
      
              self.actionQuit = QtWidgets.QAction("Quit", self)
              self.actionQuit.triggered.connect(QtWidgets.QApplication.quit)
      
              self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
      
          def closeEvent(self, event):
              QSettings.setValue("main_geometry", self.saveGeometry())
              QSettings.setValue("main_state", self.saveState())
      
      
      if __name__ == '__main__':
          main = Main()
          sys.exit(app.exec_())
      

      As that stands, when I close the main window via the "X" close-icon it does call closeEvent() to save state. However, when Quit button is clicked the QtWidgets.QApplication.quit does not invoke closeEvent().

      So having looked at posts like:

      • https://forum.qt.io/topic/39699/solved-why-qdialog-does-not-receive-a-closeevent-on-hitting-esc/3
      • https://stackoverflow.com/questions/25191954/using-the-closeevent-in-a-qt-application-does-not-close-it
      • https://stackoverflow.com/questions/22460003/pyqts-qmainwindow-closeevent-is-never-called
      • http://www.qtcentre.org/archive/index.php/t-61003.html

      I changed code to self.actionQuit.triggered.connect(self.close), expecting that to work. However, that did not call closeEvent() before exiting.

      On a whim I commented out self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True), then not only is closeEvent() not called but the window/application does not close/quit/exit either. So now I don't really understand what connecting the button to self.close is doing anyway...

      • Should self.actionQuit.triggered.connect(self.close) be all I have to do/work?
      • Why does it not work for me? Am I omitting some important detail I am not aware of?
      K Offline
      K Offline
      kshegunov
      Moderators
      wrote on 22 Sept 2017, 15:47 last edited by
      #2

      @JNBarchan said in Problem with window close/closeEvent:

      Disclaimer: I do not know Python

      then not only is closeEvent() not called

      How do you gather this? If this snippet is representative of your code, then you need to accept the event at the end of the closeEvent override. Otherwise the widget/window/dialog won't be closed and the program won't exit.

      Should self.actionQuit.triggered.connect(self.close) be all I have to do/work?

      Yes in principle.

      Read and abide by the Qt Code of Conduct

      J 1 Reply Last reply 22 Sept 2017, 15:59
      1
      • K kshegunov
        22 Sept 2017, 15:47

        @JNBarchan said in Problem with window close/closeEvent:

        Disclaimer: I do not know Python

        then not only is closeEvent() not called

        How do you gather this? If this snippet is representative of your code, then you need to accept the event at the end of the closeEvent override. Otherwise the widget/window/dialog won't be closed and the program won't exit.

        Should self.actionQuit.triggered.connect(self.close) be all I have to do/work?

        Yes in principle.

        J Offline
        J Offline
        JonB
        wrote on 22 Sept 2017, 15:59 last edited by JonB
        #3

        @kshegunov said in Problem with window close/closeEvent:

        @JNBarchan said in Problem with window close/closeEvent:

        Disclaimer: I do not know Python

        then not only is closeEvent() not called

        How do you gather this?

        I know this because I place a breakpoint at the start of closeEvent()! And it's hit when I close via window's "X" button, but not hit when I click the Quit button (when I have attached self.close as the handler)!

        If this snippet is representative of your code, then you need to accept the event at the end of the closeEvent override.
        Otherwise the widget/window/dialog won't be closed and the program won't exit.

        I could look into that. However, since the event is not called from Quit button it's not going to help me here, and when it is called from window's "X" button it all works fine just as-is....

        K 1 Reply Last reply 23 Sept 2017, 09:36
        0
        • J JonB
          22 Sept 2017, 15:59

          @kshegunov said in Problem with window close/closeEvent:

          @JNBarchan said in Problem with window close/closeEvent:

          Disclaimer: I do not know Python

          then not only is closeEvent() not called

          How do you gather this?

          I know this because I place a breakpoint at the start of closeEvent()! And it's hit when I close via window's "X" button, but not hit when I click the Quit button (when I have attached self.close as the handler)!

          If this snippet is representative of your code, then you need to accept the event at the end of the closeEvent override.
          Otherwise the widget/window/dialog won't be closed and the program won't exit.

          I could look into that. However, since the event is not called from Quit button it's not going to help me here, and when it is called from window's "X" button it all works fine just as-is....

          K Offline
          K Offline
          kshegunov
          Moderators
          wrote on 23 Sept 2017, 09:36 last edited by
          #4

          Here:

          #include <QApplication>
          #include <QMainWindow>
          #include <QAction>
          #include <QTimer>
          
          int main(int argc, char *argv[])
          {
              QApplication app(argc, argv);
              Q_UNUSED(app);
          
              QMainWindow window;
              window.show();
          
              QAction * action = new QAction(&window);
              QObject::connect(action, &QAction::triggered, &window, &QMainWindow::close);
          
              QTimer::singleShot(5000, action, &QAction::trigger);
          
              return QApplication::exec();
          }
          

          This works for me, meaning that it's not a problem with close or connecting. Either your closeEvent is discarded for some reason or the button (which is not visible in your code) is not triggering the action.

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          2
          • J Offline
            J Offline
            JonB
            wrote on 23 Sept 2017, 09:43 last edited by JonB
            #5

            @kshegunov
            Thank you for confirming that the principle is correct. I am presently debugging and discovering that the Quit button has nothing to do with the self.actionQuit = QtWidgets.QAction("Quit", self), and has some overridden code elsewhere such that it is doing its own QtWidgets.QApplication.exit() and is not connected to self.close() and hence self.closeEvent() at all :( Hence the lack of behaviour.

            I will complete this post in a few minutes, having solved the issue for me. Thank you for your help.

            EDIT: So the code I inherited declared an actionQuit and connected to a callback (just to fool me), but never actually created it in the menu via self.toolbar.addAction(self.actionQuit). The Quit button had code in a different module(!) to just do QtWidgets.QApplication.exit(), no "closing" at all. Once I traced this down I have made it call close() on main window instead and now all is well with that invoking closeEvent().

            Not my fault existing code is a labyrinthine mess, and I'm new to Qt & Python! Thanks for all help.

            1 Reply Last reply
            1

            2/5

            22 Sept 2017, 15:47

            • Login

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