PDA

View Full Version : WA_DeleteOnClose and exec()



Wasabi
7th August 2011, 04:34
I have created a child class of QDialog (NDialog). This class has WA_DeleteOnClose set up in its constructor. This is done because the parent of these dialogs persists for the duration of the entire program and there may be countless dialogs throughout the course of the program, so I'd rather not wait for the end of the program, and thus the destruction of the parent, to destroy all the countless dialogs at once. So I thought it better to simply set WA_DeleteOnClose on each dialog so that, once OK, Cancel or whatnot is pressed, the dialog gets deleted.

This works just fine, as far as I can tell.

However, the class has a static method Error which displays a modal (all others are modeless) dialog with the given error message. In this case, and this case only, WA_DeleteOnClose causes a crash. If I remove this attribute, the error dialog closes just fine, but theoretically won't be deleted until the end of the program.

Should it help, here's the relevant code:

class NDialog : public QDialog
{
Q_OBJECT

QVBoxLayout Layout;//layout box of the dialog
public:
NDialog(QString title,QWidget* parent=0, Qt::WindowFlags f=0) : QDialog(parent,f)
{
setAttribute(Qt::WA_DeleteOnClose);
setWindowTitle(title);
setLayout(&Layout);
};
void AddWidget(QWidget* widget) //add a widget to the layout
{
Layout.addWidget(widget);
};
static void Error(QString value) //diplays error message
{
NDialog* dlg = new NDialog("ERROR");
dlg->setAttribute(Qt::WA_DeleteOnClose,false);
QLabel msg(value);
dlg->AddWidget(&msg);

QPushButton ok("OK");
connect(&ok,SIGNAL(clicked()),dlg,SLOT(close()));
dlg->AddWidget(&ok);

dlg->exec();
};
};

This is the case where the code works. If I remove the "dlg->setAttribute(Qt::WA_DeleteOnClose,false);" line, the program crashes.

This is the only time I use dlg->exec() as opposed to dlg->show(). Does this have anything to do with it?

Santosh Reddy
7th August 2011, 06:06
Not sure of the crash, as you have not mentioned when the program crashes, or at least the stack trace.

Anyways following is a better, and good way to do. I recommend it this way,


class NDialog : public QDialog
{
Q_OBJECT
...
public:
...
static void Error(QString value) //diplays error message
{
NDialog dlg("ERROR");
dlg.setAttribute(Qt::WA_DeleteOnClose,false);
QLabel msg(value);
dlg.AddWidget(&msg);

QPushButton ok("OK");
connect(&ok,SIGNAL(clicked()),&dlg,SLOT(close()));
dlg.AddWidget(&ok);

dlg.exec();
};
};


or


class NDialog : public QDialog
{
Q_OBJECT
...
public:
...
static void Error(QString value) //diplays error message
{
NDialog* dlg = new NDialog("ERROR");
dlg->setAttribute(Qt::WA_DeleteOnClose,false);
QLabel* msg = QLabel(value,dlg);
dlg->AddWidget(msg);

QPushButton* ok = new QPushButton ("OK", dlg);
connect(ok,SIGNAL(clicked()),dlg,SLOT(close()));
connect(ok,SIGNAL(clicked()),dlg,SLOT(deleteLater( )));
dlg->AddWidget(ok);

dlg->exec();
};
};

for both of the above examples you don't need to use WA_DeleteOnClose flag

Wasabi
7th August 2011, 06:28
Ah, apologies. Given how the problem had to do with DeleteOnClose, I took it for granted that the crash occurs when the dialog is closed. And the erros given is a "Debug Assertion Error".

And both methods work, so thanks. What I find odd is that these dialogs work perfectly if they're modeless (::show()), but only crash when they're modal (::exec()).

Santosh Reddy
7th August 2011, 06:37
Ok, it is obvious that the WA_DeleteOnClose flag if set will delete the dialog when closed, and then as dialog is a object defined on stack it will deleted when the block scope exits, it is here your program will crash, as it is deleting the dialog which is already deleted when you closed it.

So conclusion, use WA_DeleteOnClose flag for objects / widgets created on heap.

Wasabi
7th August 2011, 06:42
Yes, of course, but you'll see in my original post that it was created on the heap, but was still giving me the crash regardless. I admit that the first time I wrote the code, I created it on the stack and it took me a few seconds to realize how silly it was, so I created it on the heap. The surprise was to find that it still crashed.

Santosh Reddy
7th August 2011, 06:46
Check again you are you missing something? You still have QLabel and QPushButton defined on stack? which were also deleted when the dialog is deleted, as dialog takes the ownership of the widget when any widget is added to it.

I hope you got my point.

Wasabi
7th August 2011, 06:54
Ah, correct. Hadn't thought to create all the other objects on the stack. Touché.

Thanks.