Re: Unable to use GUI while a process is running.

Aaron Stevens <[email protected]> Thu, 13 Nov 2008 13:11:42 -0500
Newsgroups gmane.comp.python.pythoncard
Message-ID <[email protected]>
Hi Tom,

What you need is to use multi-threading. If you are not familiar with  
multi-threading, basically a thread is a stream of execution within  
your program. The "main" thread is blocking while reading the file.  
That's why it seems unresponsive -- it keeps waiting for data, but it  
cannot respond to the user interface until it is done with the download.

A good design would be to create a separate worker thread to handle  
the download, and then have your method (in the main thread) launch  
the worker thread, and then return from the method so the UI can  
respond to other user requests. The worker thread would continue until  
the file is complete, and then exit.

You can read about threading here:
http://www.python.org/doc/2.5.2/lib/module-thread.html

Basically, you start up a thread and give it a function to execute.  
When the function ends, the thread ends with it.
You will need to use some coordination to make it possible for the  
"main" thread to read status from the worker thread, to know its  
progress. I would recommend a "push" model, whereby the worker thread  
pushes its status to the main GUI. This could be as simple as having  
it write to:

self.components.progressBar.value = int(timer)

So long as NO OTHER CODE writes to that progress bar's value. If any  
other code might also write to it, you will need to protect it using  
the LockType object described in the API page.

I hope this helps!

Best,
Aaron

On Nov 13, 2008, at 7:30 AM, Tom Angle wrote:

> I've written a program to where you enter a URL of a file to  
> download. When downloads the file and displays the progress with the  
> Gauge widget and displays the download speed. When the file is being  
> downloaded I am unable to use any buttons or type any text in the  
> window. One the download is complete the program responds the way it  
> should. How do you place the download process in the background and  
> still have the progress and speed still displayed? I may be in a  
> brain lock, but I can not figure it out.
>
> import urllib2, sre, sys, time, urllib
> from PythonCard import model
>
> class Main(model.Background):
>
>     global timer
>     global speed
>     timer = 0
>     speed = ''
>
>     def on_initialize(self, event):
>         self.components.progressBar.value = timer
>         self.components.speedField.text = speed
>
>     def on_progressBar_timer(self, event, timer):
>         self.components.progressBar.value = timer
>
>     def on_getBtn_mouseClick(self,event):
>         file_url = self.components.fileURLInput.text
>
>         lastUpdate = 0.0
>         progressSize = 0
>
>         def reportHook(count, blocksize, totalsize):
>             global lastUpdate
>             global progressSize
>             global timer
>             global speed
>
>             if count == 0:
>                 lastUpdate = time.time()
>                 progressSize = 0
>                 return
>
>             progressSize += blocksize
>             deltaTime = time.time() - lastUpdate
>
>             if deltaTime > .1:
>                 percent = int(float(count * blocksize * 100) /  
> totalsize)
>                 speed = int(progressSize / (1024 * deltaTime))
>                 timer = int(percent)
>                 speed = str(speed)
>                 speed = speed + ' kbs'
>                 self.components.progressBar.value = int(timer)
>                 self.components.speedField.text = str(speed)
>                 lastUpdate = time.time()
>                 progressSize = 0
>
>         def getName(file_url):
>             # Get file name from URL
>             farray = file_url.split('/')
>             flen = len(farray)
>             flen = flen - 1
>             return farray[flen]
>
>         def dlFile(file_url, file_name):
>             urllib.urlretrieve(file_url,file_name,reportHook)
>             print 'Done'
>             timer = 0
>             speed = ''
>             self.components.progressBar.value = timer
>             self.components.speedField.text = speed
>
>         def mainDL(file_url):
>             file_name = getName(file_url)
>             dlFile(file_url,file_name)
>
>         mainDL(file_url)
>
>     def on_exitBtn_mouseClick(self, event):
>         sys.exit(0)
>
> if __name__ == '__main__':
>     app = model.Application(Main)
>     app.MainLoop()
> -------------------------------------------------------------------------
> This SF.Net email is sponsored by the Moblin Your Move Developer's  
> challenge
> Build the coolest Linux based applications with Moblin SDK & win  
> great prizes
> Grand prize is a trip for two to an Open Source event anywhere in  
> the world
> http://moblin-contest.org/redirect.php?banner_id=100&url=/_______________________________________________
> Pythoncard-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/pythoncard-users


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/