Problem with window close/closeEvent



  • 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:

    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?

  • Qt Champions 2016

    @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.



  • @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....


  • Qt Champions 2016

    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.



  • @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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.