PDA

View Full Version : QMainWindow destroying



ecir.hana
31st March 2013, 18:40
Hello,

I try to study an example from Qt Docs:

http://qt-project.org/doc/qt-5.0/qtwidgets/mainwindows-sdi.html

I added a destructor to its QMainWindow:


MainWindow::~MainWindow()
{
qDebug() << "Hello from Destructor!";
}


and I would have expected that it prints out the message when I close the window as there is:


setAttribute(Qt::WA_DeleteOnClose);

But it does not print anything on window close event. It prints out the message number of times (= number of windows) when all of the windows are closed first.

Please, can anyone tell me why is this happening? How to make it print out the message on close event (or in the next loop of event loop)?

amleto
1st April 2013, 00:20
Yes, destructor is not the same as close event. If you want the message on close event, then put the message in the close event handler!

ecir.hana
1st April 2013, 00:58
I apologize for writing it in a bit confusing way.

When I put the message in overloaded close event handler ("void MainWindow::closeEvent(QCloseEvent *event)") it gets displayed immediately after closing the window. The problem is, when I put the message in destructor instead, it gets displayed first when the whole app quits.

So my question is: why is the destructor not called immediately after I close the window? And how to make it being called after the window is closed?

ChrisW67
1st April 2013, 04:11
When you click the [x] button (or equivalent) you are triggering a close event and (maybe) hiding the window. You are not destroying the QMainWindow object hence the destructor is not called. The QMainWindow object is not destroyed until C++ scope rules dictate (stack allocated objects) or operator delete is called (heap allocated objects).

If you use the Qt::WA_DeleteOnClose attribute a heap-allocated QWidget object will be destroyed if the object's closeEvent() accepts the closure. It uses the QObject::deleteLater() call, so the deletion is deferred until the program returns to the Qt event loop. This attribute makes no sense if the QWidget object is stack-based (often the case for the program's main window).

ecir.hana
1st April 2013, 11:49
Thank you for the reply!

Yes, I read that clicking [x] button merely hides the window and I thought Qt::WA_DeleteOnClose should destroy the window when the call returns to the event loop. The problem is that it is not happening, I run exactly the same example as linked above from the Qt Docs (I only added that debug destructor). And yes, the windows are allocated on the heap:


MainWindow *mainWin = new MainWindow;

I'm running Mac OS 10.8 and Qt 5.

I also tried to run the example in Qt 4.8 under Linux and it works. Could this be a bug on Mac? Can someone please confirm it?

Thank you for the reply!

Yes, I read that clicking [x] button merely hides the window and I thought Qt::WA_DeleteOnClose should destroy the window when the call returns to the event loop. The problem is that it is not happening, I run exactly the same example as linked above from the Qt Docs (I only added that debug destructor). And yes, the windows are allocated on the heap:


MainWindow *mainWin = new MainWindow;

I'm running Mac OS 10.8 and Qt 5.

I also tried to run the example in Qt 4.8 under Linux and it works. Could this be a bug on Mac? Can someone please confirm it?

Added after 7 minutes:

Please find the attached example bellow.

8876

Santosh Reddy
1st April 2013, 12:04
Try declaring dtor as virtual


virtual ~MainWindow();

ecir.hana
1st April 2013, 12:08
Does not help.

ecir.hana
2nd April 2013, 00:22
But thanks...

d_stranz
2nd April 2013, 00:41
So what happens if you do this in your closeEvent handler?



void MainWindow::closeEvent ( QCloseEvent * )
{
deleteLater();
}


Does the destructor get called once this method exits and control goes back to the event loop? And does your program crash shortly after that? :)

ecir.hana
2nd April 2013, 01:21
If I add the code above then yes, the destructor gets called immediately. And if I open several new windows, close one of them and the quit the whole application then yes, the program crashes too.

d_stranz
2nd April 2013, 17:31
Then it sounds like your program logic depends on having the MainWindow alive until the end of the program. If you close and delete it, and your program then crashes, then other parts of the program must be trying to use the MainWindow pointer even though it is destroyed.

The whole design idea behind QMainWindow is that it serves as the top-level "container" for all other widgets used in the application. Closing the main window implies that the application is shutting down. If you close the main window while trying to keep other windows open and the application running, then this is not the way QMainWindow was intended to be used.

ecir.hana
2nd April 2013, 17:56
Couple of points:

- if I don't add the "deleteLater()" as you suggested, it works on Linux but doesn't work on Mac. Wouldn't that imply that the bug is not in the example code?

- if I add "deleteLater()", and I close and delete the MainWindow and it crashes, couldn't it be because I left WA_DeleteOnClose set to true in closeEvent()?

- Ad "your program logic" - I took the verbatim copy of Qt oficial documentation I presume it has its logic well thought out. In fact, this is the point of my original question - I followed the documentation and it doesn't work. Why?