Gustavo Litovsky
Gustavo Litovsky

Reputation: 2487

QT quit does not call MainWindow destructor

In my application I have a tray icon and so I overrode closeEvent so that the application "minimizes" when certain things happen. However, I do expect that upon pressing exit, that the application will completely exit. However, after overriding closeEvent and calling the function quit(), it seems to bypass the MainWindow destructor, where I have some code. What am I missing in closeEvent to properly close the application so that the destructor of MainWindow is called, as is the case when closeEvent isn't overriden?

I've tried using

 QMainWindow::closeEvent(event);

and a few other things, but the destructor is never called.

My close event implementation is:

void MainWindow::closeEvent(QCloseEvent * event)
{
    if(m_closeCompletely == false)
    {
        if (trayIcon->isVisible())
        {
            QMessageBox::information(this, tr("Hello"),
                                     tr("The program will keep running in the "
                                        "system tray. To terminate the program, "
                                        "choose <b>Quit</b> in the context menu "
                                        "of the system tray entry."));
        }
    }
    else
    {
        event->accept();
    }
}

Upvotes: 2

Views: 9114

Answers (4)

Glazhoz
Glazhoz

Reputation: 41

The WA_DeleteOnClose attribute needs to be set to call the destructor on a close event, otherwise a widget or window is just hidden from view. Add the following to the class constructor:

this->setAttribute(Qt::WA_DeleteOnClose);

This will cause the destructor to be called on a close event.

Upvotes: 4

Cory Klein
Cory Klein

Reputation: 55830

I just ran into this same problem and it was because I was running an infinite loop that never allowed the application to close.

forever
{
    _runGameLoop();
}

I had to make the loop end when MainWindow closed

while(!M->isClosed())
{
    _runGameLoop();
}

And of course I had to implement isClosed()

bool MainWindow::isClosed()
{
    return _isClosed;
}

void MainWindow::closeEvent(QCloseEvent*)
{
    _isClosed = true;
}

Upvotes: 0

helsinki
helsinki

Reputation: 763

Remember that all the Application Resources are hold by the QApplication;

Once your MainWindow is closed, it just be close, aka hide from the screen;

I wonder why you want to destructor your MainWindow, it seems that you've made a system tray entry, so my suggestion is just to hide the MainWindow but to destructor, cause there is a system tray, you may want to click it to show the MainWindow.

Hope to Help. : )

Upvotes: 0

akira
akira

Reputation: 6147

It all depends on where and how you allocated the objects you are using. If you create the QApplication and QMainWindow on the heap then they will lurk around until the OS cleans up the memory. Sending a close() to a QWidget (and QMainWindow is one) will only close it .. hide it visually from the user. You can show() later on, close() does not destruct it.

You could use something like this:

int main(int argc, char* argv[]) {

   QApplication app(argc, argv);

   MyMainWindow mw;
   mw.show();

   int rc = app.exec();

   // optional: do_cleanup();

   return rc;
}

app and mw are constructed on the stack. They will be destructed in reverse order when the app returns from the exec() call (usually when you send quit() to the QCoreApplication::instance()). You can even provide a plain cleanup function, no need to put something into the destructor of the UI.

Upvotes: 2

Related Questions