[Kde-perl] a little question

Germain Garand germain at ebooksfrance.org
Thu Jan 8 00:36:45 CET 2004


Le Mercredi 07 Janvier 2004 20:32, [ slash ] a écrit :
> hi, i've a little question!
> i've observed that any operation on widget took effect after the
> esecution of the sub where the operation is contenuted in; for example:
>
> sub prova
> {
> 	textedit->setText("i'm going to download a linux distro iso");
> 	$tmp=`wget ftp://a.ftp.server/linux.iso`;
> }
>
> the text in the textedit became "i'm going to download a linux distro iso"
> only when the download is finished (and the esecution of the sub "prova" is
> terminated). Is there any way to obtain that the text of textedit became
> "i'm ..." before that the download start (before the end of the sub)
>
> Thank you all!

Hi,
maybe you need to understand better the concept of event loop driven programs.
There is nothing magically happening in the background, it's all very 
sequential.

When you say $app->exec at the end of your main program, you are merely 
telling Qt to do something like this pseudo code:

while ( ! shouldQuit() ) {
       processSomeEvents();
       sleepSomeNanoSeconds();
}

processSomeEvents() here calls your perl sub whenever something interesting it 
happens (a button is clicked, a timer is elapsed, etc...)
and wait for it to return...

So obviously, if your perl sub doesn't return, the event loop is totally 
*blocked*. Nothing will refresh, no timer will be called, nothing at all will 
happen except what you are doing in your sub.

The only way to have things "happening" is to go back to the event loop
(by returning from your sub) and let it process the accumulated events (e.g: 
in your case, the schedduled repaint of your textedit widget :-).

Things may sometime look a bit more "magical" because Qt has a recursive event 
loop: some methods may call it again for a while, then return (possibly after 
having called other methods in-between, which may call again the eventLoop, 
which may call other methods, etc...), but you should never forget that it 
all boils down to a _sequence_ of operations and that your program is a part 
of that sequence.

sub foo {
     doSomething();
     while( next_short_slice_of_long_operation() )
     {
	Qt::app()->processEvents(); # go back to the event loop for a while...
    }
    doSomethingElse();
}

So the answer to your question is one of:

- find a Qt class that can do this operation in a clean non-blocking way, with 
nice progress signals e tutti quanti
  (the QUrlOperator class we were discussing yesterday on the list look very 
fine for your example... have a look at the Network Module documentation)

- or slice your long operation and periodically call processEvents()
  (possibly with a filter blocking user input - e.g:
    Qt::app()->eventLoop()->processEvents( &Qt::EventLoop::ExcludeUserInput)

- or slice your long operation and have the slices done regularly via a 
Qt::Timer/Qt::Object::startTimer()

- or find a perl module that will work asynchronously and has some mean to 
call you back 

- or use a Qt::Process or whatever other mean to launch your long operation in 
the background and control it

- or, as a _very last_ resort, use a perl thread as explained here:
http://cvs.sourceforge.net/viewcvs.py/perlqt/PerlQt-3/PerlQt/examples/perl_threads/ 


Germain


More information about the Kde-perl mailing list