Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 5

Qt-interest Archive, July 2007
qApp->processEvents and QEventLoop


Message 1 in thread

I have a code where call QProgressDialog, in qt assistant i see example 
where using qApp->processEvents. I read what each modal dialog have 
local QEventLoop, so this is mean, what QProgressDialog can repaint and 
updates whithout "qApp->processEvents" ? This important for me, becouse
my program still can use if i press button who call longest time execute 
with many small files, and if user can use program may be potential crash.

--
 [ signature omitted ] 

Message 2 in thread

SABROG schrieb:
> I have a code where call QProgressDialog, in qt assistant i see example 
> where using qApp->processEvents. I read what each modal dialog have 
> local QEventLoop, so this is mean, what QProgressDialog can repaint and 
> updates whithout "qApp->processEvents" ? This important for me, becouse
> my program still can use if i press button who call longest time execute 
> with many small files, and if user can use program may be potential crash.

Hmmm, I must admit that I had a bit of difficulties understanding what 
the actual question/concern is, so here's just generally how a 
QProgressDialog works:

The dialog is modal, that is as long as it is shown (by calling exec()) 
the user cannot interact with the rest of the application. The only 
option the user has is to click on the "Cancel" button. So the answer 
would be "No", the user cannot interact with the program as long as you 
are doing a lengthy operation, for example copying a lot of small files.

Then when calling QProgressDialog::exec() (which shows the dialog as a 
"modal" dialog, as explained above) you indeed start the internal event 
loop of that dialog. Operations such as network operations or QTimers 
which require a running event loop can operate as expected. Also 
updating the widgets (repaint) is possible (e.g. as a reaction to an 
incoming network packet or whenever a file has been copied etc.).

So again the answer would be "No", you don't need to call 
qApp->processEvents in your lengthy operation code. The QProgressDialog 
is already running an event loop for you.

All your code has to do then and when is to emit a progress(int done, 
int total) signal so that the QProgressDialog can update the progress 
bar (simply connect your signal to the proper slot of the QProgressBar 
and you are done).

Also you need to provide some kind of an abort() method which closes all 
file handles, deletes only partially copied files etc. ("clean up") and 
off course aborts the current lengthy operation when the user clicks on 
"Cancel".

Does that answer your questions?

Cheers, Oliver

p.s. All the above is valid for Qt 3; but I guess it still holds for Qt 4 ;)

--
 [ signature omitted ] 

Message 3 in thread

Till Oliver Knoll пишет:
> The dialog is modal, that is as long as it is shown (by calling exec()) 
> the user cannot interact with the rest of the application. The only 
> option the user has is to click on the "Cancel" button. So the answer 
> would be "No", the user cannot interact with the program as long as you 
> are doing a lengthy operation, for example copying a lot of small files.

My users can, becouse QProgressDialog class create each time when enter 
inside my method. This method calls on each file. So, if i manually call
qApp->processEvents(), when method return and QProgressDialog delete, i 
see what mainwindow react with buttons and clicks, but if i remove 
qApp->processEvent from code - all ok. I read in assistant about modal 
dialogs and what they call QApplication::processEvents(), but i don't 
undrestand what different with manual calling and calling inside dialogs.

I found answer on my question inside Assistant:

"
Using a modal QProgressDialog is simpler for the programmer, but you 
must call QApplication::processEvents() or 
QEventLoop::processEvents(ExcludeUserInput) to keep the event loop 
running to ensure that the application doesn't freeze. Do the operation 
in a loop, call setValue() at intervals, and check for cancellation with 
wasCanceled(). For example:
      QProgressDialog progress("Copying files...", "Abort Copy", 0, 
numFiles, this);
      progress.setWindowModality(Qt::WindowModal);

      for (int i = 0; i < numFiles; i++) {
          progress.setValue(i);
          qApp->processEvents();

          if (progress.wasCanceled())
              break;
          //... copy one file
      }
      progress.setValue(numFiles);
"

So i have back situation, i WANT freeze application :)
Thanks for reply.

--
 [ signature omitted ] 

Message 4 in thread

SABROG schrieb:
> Till Oliver Knoll пишет:
>> The dialog is modal, that is as long as it is shown (by calling 
>> exec()) the user cannot interact with the rest of the application. The 
>> only option the user has is to click on the "Cancel" button. So the 
>> answer would be "No", the user cannot interact with the program as 
>> long as you are doing a lengthy operation, for example copying a lot 
>> of small files.
> 
> My users can, becouse QProgressDialog class create each time when enter 
> inside my method. This method calls on each file.

I would not do that: create *one* QProgressDialog for *all* file copy 
operations and show the "number of already copied files and the total 
number of files", if possible.

You could implement your custom progress dialog and show a 2nd progress 
bar for the current file ("bytes already copied").

> So, if i manually call
> qApp->processEvents(), when method return and QProgressDialog delete, i 
> see what mainwindow react with buttons and clicks, but if i remove 
> qApp->processEvent from code - all ok. I read in assistant about modal 
> dialogs and what they call QApplication::processEvents(), but i don't 
> undrestand what different with manual calling and calling inside dialogs.

Okay, I have to correct my previous post a bit. I said that you do not 
need to call qApp->processEvents() yourself. This is (partially) wrong: 
*only* if you call QProgressDialog::exec() you don't need to do this.

The method exec() (coming from QDialog base class) is *blocking*: it 
starts it's own event loop (and hence you really don't need to call 
qApp->processEvents()).

But off course this only works when you have an *event-driven* operation 
going on, based on QTimers or on network operations such as QFtp (I just 
implemented such a QProgressDialog for my "FTP synchroniser", hence my 
thoughts were a bit biased towards this scenario ;) ).

But if you really need your own "computation loop" running, for example 
your said file copy loop (which iterates over all files to be copied), 
then you cannot call exec(), off course.

Then you need to go for the approach as described in the Qt docs, 
creating a *modal* QProgressDialog, calling setValue() on it when needed 
and give the Qt event loop a chance to handle pending processes such as 
repaint events.

> I found answer on my question inside Assistant:

In your case you have to go for this approach. Actually the example code 
given there is pretty much what you need ;)

> So i have back situation, i WANT freeze application :)
> Thanks for reply.

As suggested above, create *one* progress dialog for all files to be 
copied, make sure it is "application modal" (set proper flag in 
constructor of QProgressDialog) and you should be fine.

Cheers, Oliver

--
 [ signature omitted ]