Newbie doing lengthy initialization with Tkinter gui

P

Pasi Oja-Nisula

I have written a small image viewer application for
sorting out photos downloaded from camera. This was quite easy,
thanks to the great Python Imaging Library. Since the loading and
thumbnailing phase takes a while at the start of the program,
I figured that it would be nice to show the gui and put some kind
of "loading image 25/50" text there while processing the images.
So now I construct the simple Tkinter gui in init and when mainloop
is called the gui is shown.

The question is how (or where) can I call my loadImages function right
after the mainloop starts? Or is there a better way to do this?

Pasi
 
M

Maric Michaud

Le dimanche 13 août 2006 12:39, Pasi Oja-Nisula a écrit :
The question is how (or where) can I call my loadImages function right
after the mainloop starts? Or is there a better way to do this?
Seems a good use case for multi-thread, try something like this :

In [28]: import Tix

In [29]: main=Tix.Tk()

In [30]: p=Tix.Meter(main)

In [31]: p.pack()

In [32]: def process(progress) :
....: from time import sleep
....: for i in range(10) :
....: sleep(1)
....: p.configure(value=float(p.cget('value'))+0.1)
....:
....:


In [33]: import thread

In [34]: thread.start_new_thread(process, (p,)) and main.mainloop()

Of course the last line is tricky, the thread should be started by the
App(Tix.Tk) mainloop.


--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
 
J

jmdeschamps

Maric said:
Le dimanche 13 août 2006 12:39, Pasi Oja-Nisula a écrit :
The question is how (or where) can I call my loadImages function right
after the mainloop starts? Or is there a better way to do this?
Seems a good use case for multi-thread, try something like this :

In [28]: import Tix

In [29]: main=Tix.Tk()

In [30]: p=Tix.Meter(main)

In [31]: p.pack()

In [32]: def process(progress) :
....: from time import sleep
....: for i in range(10) :
....: sleep(1)
....: p.configure(value=float(p.cget('value'))+0.1)
....:
....:


In [33]: import thread

In [34]: thread.start_new_thread(process, (p,)) and main.mainloop()

Of course the last line is tricky, the thread should be started by the
App(Tix.Tk) mainloop.


--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097

Tkinter also has a timer-type function called *after*. Use this to call
your init function just befrore the mainloop call. You gui wil show up
and you can then update it to show progress as you wish
No neep for thread or Tix modules...!

Here's a working example:
#################
from Tkinter import *
# Your progress showing function
def showProgress(i):
# Tell the gui to show some progress here
obj=c.find_withtag("job")[0]
c.itemconfig(obj,text="Ok from job is up to "+str(i))
c.update()

# Your app init function
def doInitOne():
#Do some init work here
for i in range(100):
for j in range(100):
for k in range(100):
for m in range(100):
a=1
# Once in a while update the gui
showProgress(i)

# your main app
root=Tk()
c=Canvas(root,bg="yellow",width=300,height=300)
monobj=c.create_text(100,200,text="Some ",tags="job")
c.pack()
# this will *sleep* one millisec before calling
# your doInitOne function and continue
# with the rest of the code during that sleep time
# in this case just the mainloop
root.after(1, doInitOne)
root.mainloop()
 
P

Pasi Oja-Nisula

Tkinter also has a timer-type function called *after*. Use this to call
your init function just befrore the mainloop call. You gui wil show up
and you can then update it to show progress as you wish
No neep for thread or Tix modules...!

Thanks for the great example! I hoped that there would be a simple way
to show the progress and this is just what I was looking for.

Pasi
 
M

Maric Michaud

Le dimanche 13 août 2006 16:01, (e-mail address removed) a écrit :
No neep for thread or Tix modules...!

Module thread is always available (at less on platforms where Tkinter is
available), while Tix in my example is just intended to use the Meter widget
(a progress bar).
# this will *sleep* one millisec before calling
# your doInitOne function and continue
# with the rest of the code during that sleep time
# in this case just the mainloop
root.after(1, doInitOne)
root.mainloop()

hum, this has not exactly the same effect, after, after_cancel, etc. are for
scheduling actions in the future, and when the action start, it will block
the mainloop and user interaction (this is why you need to call explicitly
the update method), so the gui will not respond anymore.

Finally why do you differ the call of your function after the mainloop since
it will block ?

That's said, I remember now that there isn't anything in Tkinter (no events
or callbacks) to get the 'mainloop started' hook, so you must start the
thread before the mainloop, probably like this :

class myApp(Toplevel) :

def mainloop(self) :
start_new_thread(initFunc, params)
Toplevel.mainloop(self)

--
_____________

Maric Michaud
_____________

Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,217
Latest member
topweb3twitterchannels

Latest Threads

Top