PDA

View Full Version : QDialog: show() and exec() together in constructor?



Teuniz
27th February 2007, 09:01
I'm using a QDialog. In the constructor I need to do some time-consuming stuff. Therfore it looks like this:

constructor
{
initialize widgets, buttons, etc.
mydialog->show();
do some timeconsuming stuff
mydialog->exec();
}

My question is, is it valid/legal to use show() and exec() in the same constructor?
I tried and everything works well but I want to know for sure.

zlatko
27th February 2007, 09:52
Em..interesting question :) Yes its correct, but why do you need it ?
exec() - show your dialog as modal window;
show() - show your dialog as standart widget;

jpn
27th February 2007, 10:11
Hmm, I doubt it does what it's intended to do. Calling show() doesn't show the dialog immediately but schedules a show event which the dialog will receive later when the control returns to the event loop. Calling exec() makes the dialog appear because the dialog will start it's own event loop.

Teuniz
27th February 2007, 10:30
exec() blocks till the dialog gets closed, show() doesn't.

If I do like this:


constructor
{
initialize widgets, buttons, etc.
do some timeconsuming stuff
mydialog->exec();
}

it will take a long time till the user sees the dialog because of the time consuming stuff in the constructor.

If I do like this:


constructor
{
initialize widgets, buttons, etc.
mydialog->exec();
do some timeconsuming stuff
}

then the timeconsuming stuff will be done AFTER the user closed the dialog

If I do like this:


constructor
{
initialize widgets, buttons, etc.
mydialog->show();
do some timeconsuming stuff
}

then the parent window/widget will continue (the dialog will not block) and that's not what I want.

Regards.

jpn
27th February 2007, 11:12
exec() blocks till the dialog gets closed, show() doesn't.
Yes, that's the difference between modal and modeless dialogs. But calling show() before the time consuming task doesn't bring the dialog visible until exec() gets called, unless you call QCoreApplication::processEvents() during the time consuming task. There is a little pitfall in this, though, because the dialog would end up being modeless during the time consuming task and turn to a modal dialog after the task is finished and exec() is called. This can be avoided by calling QDialog::setModal(true) before the time consuming task.



MyDialog d; // it's safe to allocate the dialog on the stack, because exec() blocks
mydialog.setModal(true);
mydialog.show();
for (...)
{
// do one part of the time consuming task
qApp->processEvents(); // let the app process it's events every once in a while
}
mydialog.exec(); // let the dialog start it's own event loop

wysota
27th February 2007, 11:32
How about:

MyDialog d;
QTimer::singleShot(0, &d, SLOT(doTimeConsumingTask()));
d.exec();

This should execute the slot immediately when d.exec() is called (provided that the event will not make it to a wrong queue). The drawback is that you will block the event loop if you do everything in the slot at once. So either do it the way J-P mentioned or split the task into subtasks, put each in a separate slot and as the last line of each slot start a timer that will trigger the next slot.

Teuniz
27th February 2007, 11:37
Yes, I discovered this by trial and error :) Thanks anyway for your good explanation.

By the way, instead of using

qApp->processEvents();
I use

for(i=0; i<10; i++) qApp->processEvents();
because I have the impression that (specially under Windows) calling processEvents() only
one time isn't always enough when the OS is very busy (widgets aren't painted completely etc.).

Regards.

wysota
27th February 2007, 11:40
processEvents() processes all events pending. The problem widgets are not painted is because you made the processor very busy. Instead use slots that'll get triggered every 100ms or so - the task will do its job slower, but the system stability will be sustained.

Teuniz
28th February 2007, 11:43
I will use the solution with the QTimer, it gives better results than using qApp->processEvents();

Thanks for your help.