osdir.com
mailing list archive F.A.Q. -since 2001!



Subject: Re: tkinter "monitor" and
root.mainloop() - msg#00014

List: python.tkinter

Mail Archive Navigation:
by Date: Prev Next Date Index by Thread: Prev Next Thread Index

True, sleep() pauses the main app - if you run it there. It wasn't obvious to me from the original question that this might be a problem :-)

In my application (a simple egg timer that allows on the fly creation of new timers and allows timing in relative or absolute terms i.e. in 5 minutes 23 seconds alert me or at 10:06:55 alert me) I leave the sleep() call down in the thread that I created for each timer - so each "timer" thread pauses for X seconds (1 second in my case because that is the smallest increment of time that I am interested in).

I use Pmw for all my GUI work - after getting your mind around how flexible it can be, you can create some amazingly power applications that can reconfigure themselves on the fly for the user - one of the best programming interfaces I have ever used! The guy who did this has my complete admiration! :-)

Perhaps (just for fun :-)) think about recreating your application using threads and (message) queues to pass information between the main Tk loop and the various threads that you create.

Be careful - Tkinter in not re-entrant and you need to leave all of your graphics manipulations in the mainloop - but you can safely do all sorts of other stuff (checking files for changes etc etc) in threads - as long as they don't do any GUI work then you are safe.

Doing threaded applications in Tk is definitely not for the beginner - you can find cookbook examples of using threading with Tk.

Personally I find it kind of fun to do - I work in real-time embedded systems programming, so threading and tasking is very familiar territory. But if you ever want to expand your horizons give it some thought - but be mindful that it requires a different mindset to that of straight "linear" thinking programming - many programmers have some difficulty when they are first exposed to threads and multi-tasking applications - but once you get past that barrier you start to think in those terms with ease :-)

Peter

On Mon, May 26, 2008 at 6:00 AM, Cameron Laird <Cameron@xxxxxxxxxxx> wrote:
On Fri, May 23, 2008 at 02:52:44PM +0000, Cameron Laird wrote:
>                       .
>                       .
>                       .
> > and thanks for the answers: how, i avoided the sleep() approach,
> > because, as Cameron said i supposed that it freezed the application:
> > being in sleep() it stops the mainloop()...
> >
> > Now,
> >
> > i have used the after() approach, with some satisfactory results,
> > only, there is something that still bugs me: if i understand correctly
> > after() tells the loop to execute someething after some time (in
> > milliseconds). What i'd like to do is something more like every()...
> > In fact, i'd like the application to be redrawn every() second (so to
> > say), while, if i understand correctly, every time i want to redraw
> > the application (for example because in the meantime the log i'm
> > monitoring has changed) i have to call after(). In this sense i have
> > put an after() at the end of every possible event that the user, while
> > working on the interface, could do. But, if nothing happens at the GUI
> > level, then nothing is updated.
> >
> > I'd prefer to avoid to put a "UPDATE" button on the app, but as of
> > now, seems like it's the only way to do it safely.
> >
> > I am wrong?
>                       .
>                       .
>                       .
> Yes and no.
>
> every() is a common need among Tkinter() programmers,
> for all the reasons you describe.  I'm sure several
> of us have written our own version, but, to my
> surprise--astonishment!--I can't put my hands on one
> of them in public space just now.
>
> I'm late for a meeting myself; I'll summarize:
> A.  You do NOT need to have after()s all
>     over the widget tree, although I can
>     understand the confusion;
> B.  All that's necessary is a single
>     "free-running" after() *that
>     invokes itself*; and
> C.  After I get out of my meetings, I'll
>     write an example.
                       .
                       .
                       .
I need to put this minimal example of after()-based polling in the Wiki ...

 import Tkinter
 import time

 root = Tkinter.Tk()

 def my_update():
     display.set("The time now is '%s'." % time.asctime(time.localtime()))
         # Re-invoke myself in two seconds.
     root.after(2000, my_update)

 display = Tkinter.StringVar()
 window = Tkinter.Label(root, textvariable = display)
 window.pack()
 my_update()
 root.mainloop()

The effect is to create a textual clock which updates every two seconds,
while keeping the window "live".
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss@xxxxxxxxxx
http://mail.python.org/mailman/listinfo/tkinter-discuss

_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss@xxxxxxxxxx
http://mail.python.org/mailman/listinfo/tkinter-discuss

Thread at a glance:

Previous Message by Date:

Re: tkinter "monitor" and root.mainloop()

On Fri, May 23, 2008 at 02:52:44PM +0000, Cameron Laird wrote: > . > . > . > > and thanks for the answers: how, i avoided the sleep() approach, > > because, as Cameron said i supposed that it freezed the application: > > being in sleep() it stops the mainloop()... > > > > Now, > > > > i have used the after() approach, with some satisfactory results, > > only, there is something that still bugs me: if i understand correctly > > after() tells the loop to execute someething after some time (in > > milliseconds). What i'd like to do is something more like every()... > > In fact, i'd like the application to be redrawn every() second (so to > > say), while, if i understand correctly, every time i want to redraw > > the application (for example because in the meantime the log i'm > > monitoring has changed) i have to call after(). In this sense i have > > put an after() at the end of every possible event that the user, while > > working on the interface, could do. But, if nothing happens at the GUI > > level, then nothing is updated. > > > > I'd prefer to avoid to put a "UPDATE" button on the app, but as of > > now, seems like it's the only way to do it safely. > > > > I am wrong? > . > . > . > Yes and no. > > every() is a common need among Tkinter() programmers, > for all the reasons you describe. I'm sure several > of us have written our own version, but, to my > surprise--astonishment!--I can't put my hands on one > of them in public space just now. > > I'm late for a meeting myself; I'll summarize: > A. You do NOT need to have after()s all > over the widget tree, although I can > understand the confusion; > B. All that's necessary is a single > "free-running" after() *that > invokes itself*; and > C. After I get out of my meetings, I'll > write an example. . . . I need to put this minimal example of after()-based polling in the Wiki ... import Tkinter import time root = Tkinter.Tk() def my_update(): display.set("The time now is '%s'." % time.asctime(time.localtime())) # Re-invoke myself in two seconds. root.after(2000, my_update) display = Tkinter.StringVar() window = Tkinter.Label(root, textvariable = display) window.pack() my_update() root.mainloop() The effect is to create a textual clock which updates every two seconds, while keeping the window "live".

Next Message by Date:

Re: tkinter "monitor" and root.mainloop()

On Mon, May 26, 2008 at 11:29:40AM +1000, Peter Milliken wrote: . . . > True, sleep() pauses the main app - if you run it there. It wasn't obvious > to me from the original question that this might be a problem :-) > > In my application (a simple egg timer that allows on the fly creation of new > timers and allows timing in relative or absolute terms i.e. in 5 minutes 23 > seconds alert me or at 10:06:55 alert me) I leave the sleep() call down in > the thread that I created for each timer - so each "timer" thread pauses for > X seconds (1 second in my case because that is the smallest increment of > time that I am interested in). > > I use Pmw for all my GUI work - after getting your mind around how flexible > it can be, you can create some amazingly power applications that can > reconfigure themselves on the fly for the user - one of the best programming > interfaces I have ever used! The guy who did this has my complete > admiration! :-) > > Perhaps (just for fun :-)) think about recreating your application using > threads and (message) queues to pass information between the main Tk loop > and the various threads that you create. > > Be careful - Tkinter in not re-entrant and you need to leave all of your > graphics manipulations in the mainloop - but you can safely do all sorts of > other stuff (checking files for changes etc etc) in threads - as long as > they don't do any GUI work then you are safe. > > Doing threaded applications in Tk is definitely not for the beginner - you > can find cookbook examples of using threading with Tk. > > Personally I find it kind of fun to do - I work in real-time embedded > systems programming, so threading and tasking is very familiar territory. > But if you ever want to expand your horizons give it some thought - but be > mindful that it requires a different mindset to that of straight "linear" > thinking programming - many programmers have some difficulty when they are > first exposed to threads and multi-tasking applications - but once you get > past that barrier you start to think in those terms with ease :-) > > > . > > > . > > > . > > > > and thanks for the answers: how, i avoided the sleep() approach, > > > > because, as Cameron said i supposed that it freezed the application: > > > > being in sleep() it stops the mainloop()... > > . > > . > > . > > I need to put this minimal example of after()-based polling in the Wiki ... > > > > import Tkinter > > import time > > > > root = Tkinter.Tk() > > > > def my_update(): > > display.set("The time now is '%s'." % time.asctime(time.localtime())) > > # Re-invoke myself in two seconds. > > root.after(2000, my_update) > > > > display = Tkinter.StringVar() > > window = Tkinter.Label(root, textvariable = display) > > window.pack() > > my_update() > > root.mainloop() . . . I think we're all together now. To be certain, I'll say some of this in my own words. sleep() is not a "problem", but it frequently is a *surprise* to those working in this area for the first time. Concurrency is indeed distinct from sequential- procedural patterns, and I agree that folklore tells us many newcomers to the area take a bit of time to adjust. I'd add that, to the best of my knowledge, that adjustment is present whether coding is in a thread-based or event-based idiom. While I'm also a firm believer that the latter is less error-prone for many common requirement sets, I agree that Pmw is a considerable value for which we all should be thankful. You're absolutely right that Tkinter (and X-windows- compatible toolkits, more generally) need to keep their GUIs in a single thread. Is it handy for you to share a threaded-Pmw-based equi- valent of the two-second-grainy clock I've included above? I think it'll make for an interesting comparison from which we perhaps might all learn. If you don't get to it in the next week, I'll try, although I'm rusty with Pmw.

Previous Message by Thread:

Re: tkinter "monitor" and root.mainloop()

On Fri, May 23, 2008 at 02:52:44PM +0000, Cameron Laird wrote: > . > . > . > > and thanks for the answers: how, i avoided the sleep() approach, > > because, as Cameron said i supposed that it freezed the application: > > being in sleep() it stops the mainloop()... > > > > Now, > > > > i have used the after() approach, with some satisfactory results, > > only, there is something that still bugs me: if i understand correctly > > after() tells the loop to execute someething after some time (in > > milliseconds). What i'd like to do is something more like every()... > > In fact, i'd like the application to be redrawn every() second (so to > > say), while, if i understand correctly, every time i want to redraw > > the application (for example because in the meantime the log i'm > > monitoring has changed) i have to call after(). In this sense i have > > put an after() at the end of every possible event that the user, while > > working on the interface, could do. But, if nothing happens at the GUI > > level, then nothing is updated. > > > > I'd prefer to avoid to put a "UPDATE" button on the app, but as of > > now, seems like it's the only way to do it safely. > > > > I am wrong? > . > . > . > Yes and no. > > every() is a common need among Tkinter() programmers, > for all the reasons you describe. I'm sure several > of us have written our own version, but, to my > surprise--astonishment!--I can't put my hands on one > of them in public space just now. > > I'm late for a meeting myself; I'll summarize: > A. You do NOT need to have after()s all > over the widget tree, although I can > understand the confusion; > B. All that's necessary is a single > "free-running" after() *that > invokes itself*; and > C. After I get out of my meetings, I'll > write an example. . . . I need to put this minimal example of after()-based polling in the Wiki ... import Tkinter import time root = Tkinter.Tk() def my_update(): display.set("The time now is '%s'." % time.asctime(time.localtime())) # Re-invoke myself in two seconds. root.after(2000, my_update) display = Tkinter.StringVar() window = Tkinter.Label(root, textvariable = display) window.pack() my_update() root.mainloop() The effect is to create a textual clock which updates every two seconds, while keeping the window "live".

Next Message by Thread:

Re: tkinter "monitor" and root.mainloop()

On Mon, May 26, 2008 at 11:29:40AM +1000, Peter Milliken wrote: . . . > True, sleep() pauses the main app - if you run it there. It wasn't obvious > to me from the original question that this might be a problem :-) > > In my application (a simple egg timer that allows on the fly creation of new > timers and allows timing in relative or absolute terms i.e. in 5 minutes 23 > seconds alert me or at 10:06:55 alert me) I leave the sleep() call down in > the thread that I created for each timer - so each "timer" thread pauses for > X seconds (1 second in my case because that is the smallest increment of > time that I am interested in). > > I use Pmw for all my GUI work - after getting your mind around how flexible > it can be, you can create some amazingly power applications that can > reconfigure themselves on the fly for the user - one of the best programming > interfaces I have ever used! The guy who did this has my complete > admiration! :-) > > Perhaps (just for fun :-)) think about recreating your application using > threads and (message) queues to pass information between the main Tk loop > and the various threads that you create. > > Be careful - Tkinter in not re-entrant and you need to leave all of your > graphics manipulations in the mainloop - but you can safely do all sorts of > other stuff (checking files for changes etc etc) in threads - as long as > they don't do any GUI work then you are safe. > > Doing threaded applications in Tk is definitely not for the beginner - you > can find cookbook examples of using threading with Tk. > > Personally I find it kind of fun to do - I work in real-time embedded > systems programming, so threading and tasking is very familiar territory. > But if you ever want to expand your horizons give it some thought - but be > mindful that it requires a different mindset to that of straight "linear" > thinking programming - many programmers have some difficulty when they are > first exposed to threads and multi-tasking applications - but once you get > past that barrier you start to think in those terms with ease :-) > > > . > > > . > > > . > > > > and thanks for the answers: how, i avoided the sleep() approach, > > > > because, as Cameron said i supposed that it freezed the application: > > > > being in sleep() it stops the mainloop()... > > . > > . > > . > > I need to put this minimal example of after()-based polling in the Wiki ... > > > > import Tkinter > > import time > > > > root = Tkinter.Tk() > > > > def my_update(): > > display.set("The time now is '%s'." % time.asctime(time.localtime())) > > # Re-invoke myself in two seconds. > > root.after(2000, my_update) > > > > display = Tkinter.StringVar() > > window = Tkinter.Label(root, textvariable = display) > > window.pack() > > my_update() > > root.mainloop() . . . I think we're all together now. To be certain, I'll say some of this in my own words. sleep() is not a "problem", but it frequently is a *surprise* to those working in this area for the first time. Concurrency is indeed distinct from sequential- procedural patterns, and I agree that folklore tells us many newcomers to the area take a bit of time to adjust. I'd add that, to the best of my knowledge, that adjustment is present whether coding is in a thread-based or event-based idiom. While I'm also a firm believer that the latter is less error-prone for many common requirement sets, I agree that Pmw is a considerable value for which we all should be thankful. You're absolutely right that Tkinter (and X-windows- compatible toolkits, more generally) need to keep their GUIs in a single thread. Is it handy for you to share a threaded-Pmw-based equi- valent of the two-second-grainy clock I've included above? I think it'll make for an interesting comparison from which we perhaps might all learn. If you don't get to it in the next week, I'll try, although I'm rusty with Pmw.
blog comments powered by Disqus

Home | News | Sitemap | FAQ | advertise | OSDir is an Inevitable website. GBiz is too!