Discussion:
[Tkinter-discuss] loop delay
Paul Simon
2012-10-21 22:31:06 UTC
Permalink
I' m a novice python programmer and now starting to learn tkinter for a
front and db back end to replace an application written MS Access/VBA. The
following program doesn't work as I expected as data is not written to the
text box until the def is exited. If I include a print statement with the
increment it is printed.

Any suggestions are welcome.

from Tkinter import *

from time import sleep

def count (event):

#while n < 2:

for n in range(2):

print str(n)

text_button.insert(2.0, str(n))

sleep (2)


root = Tk()

root.geometry("300x300+10+10")

frame = Frame(root,bg="red", width=100,height=100)

text_button = Text(frame,fg ="green",bg="blue",height=1,width=7)

text_button.bind("<Button-1>",count)

text_button.pack(side=LEFT)

quit_button = Button(frame, text="QUIT",fg="red", command=root.destroy)

quit_button.pack(side=LEFT)

frame.pack()

root.mainloop()

-------------------------------

Paul Simon
Lynn Oliver
2012-10-22 02:17:07 UTC
Permalink
Maybe the idle loop needs to run so things get done. Try calling update_idletasks(). Be nice to have some indents...

Lynn
Post by Paul Simon
I' m a novice python programmer and now starting to learn tkinter for a
front and db back end to replace an application written MS Access/VBA. The
following program doesn't work as I expected as data is not written to the
text box until the def is exited. If I include a print statement with the
increment it is printed.
Any suggestions are welcome.
from Tkinter import *
from time import sleep
print str(n)
text_button.insert(2.0, str(n))
sleep (2)
root = Tk()
root.geometry("300x300+10+10")
frame = Frame(root,bg="red", width=100,height=100)
text_button = Text(frame,fg ="green",bg="blue",height=1,width=7)
text_button.bind("<Button-1>",count)
text_button.pack(side=LEFT)
quit_button = Button(frame, text="QUIT",fg="red", command=root.destroy)
quit_button.pack(side=LEFT)
frame.pack()
root.mainloop()
-------------------------------
Paul Simon
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss at python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tkinter-discuss/attachments/20121021/d72c9dc4/attachment.html>
Paul Simon
2012-10-22 03:39:59 UTC
Permalink
Thank you! Just what I was looking for and will have to re-read the documentation. Sorry about the indents: Copying from linux to windows sometimes does some strange things and although I tried to fix it...

Paul
"Lynn Oliver" <raycores at gmail.com> wrote in message news:7BF8A3B5-45A3-499C-89C8-34F1EC25103A at gmail.com...
Maybe the idle loop needs to run so things get done. Try calling update_idletasks(). Be nice to have some indents...


Lynn



On Oct 21, 2012, at 3:31 PM, Paul Simon <psimon at sonic.net> wrote:


I' m a novice python programmer and now starting to learn tkinter for a
front and db back end to replace an application written MS Access/VBA. The
following program doesn't work as I expected as data is not written to the
text box until the def is exited. If I include a print statement with the
increment it is printed.

Any suggestions are welcome.

from Tkinter import *

from time import sleep

def count (event):

#while n < 2:

for n in range(2):

print str(n)

text_button.insert(2.0, str(n))

sleep (2)


root = Tk()

root.geometry("300x300+10+10")

frame = Frame(root,bg="red", width=100,height=100)

text_button = Text(frame,fg ="green",bg="blue",height=1,width=7)

text_button.bind("<Button-1>",count)

text_button.pack(side=LEFT)

quit_button = Button(frame, text="QUIT",fg="red", command=root.destroy)

quit_button.pack(side=LEFT)

frame.pack()

root.mainloop()

-------------------------------

Paul Simon



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





------------------------------------------------------------------------------


_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss at python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tkinter-discuss/attachments/20121021/3bff4a9c/attachment.html>
Lynn Oliver
2012-10-22 04:02:41 UTC
Permalink
My experience, which admittedly is limited, has been that a lot of the ins and outs are not well documented.

For my current program I went through three iterations of the UI: the first when I found out about validators; the second when I learned how to use trace functions; and (hopefully) the last when I realized I could just bind the key_up events and do everything I needed right there.
Post by Paul Simon
Thank you! Just what I was looking for and will have to re-read the documentation. Sorry about the indents: Copying from linux to windows sometimes does some strange things and although I tried to fix it...
Paul
Maybe the idle loop needs to run so things get done. Try calling update_idletasks(). Be nice to have some indents...
Lynn
Post by Paul Simon
I' m a novice python programmer and now starting to learn tkinter for a
front and db back end to replace an application written MS Access/VBA. The
following program doesn't work as I expected as data is not written to the
text box until the def is exited. If I include a print statement with the
increment it is printed.
Any suggestions are welcome.
from Tkinter import *
from time import sleep
print str(n)
text_button.insert(2.0, str(n))
sleep (2)
root = Tk()
root.geometry("300x300+10+10")
frame = Frame(root,bg="red", width=100,height=100)
text_button = Text(frame,fg ="green",bg="blue",height=1,width=7)
text_button.bind("<Button-1>",count)
text_button.pack(side=LEFT)
quit_button = Button(frame, text="QUIT",fg="red", command=root.destroy)
quit_button.pack(side=LEFT)
frame.pack()
root.mainloop()
-------------------------------
Paul Simon
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss at python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss at python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
_______________________________________________
Tkinter-discuss mailing list
Tkinter-discuss at python.org
http://mail.python.org/mailman/listinfo/tkinter-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tkinter-discuss/attachments/20121021/7c288313/attachment-0001.html>
Bryan Oakley
2012-10-22 11:13:07 UTC
Permalink
Post by Paul Simon
I' m a novice python programmer and now starting to learn tkinter for a
front and db back end to replace an application written MS Access/VBA. The
following program doesn't work as I expected as data is not written to the
text box until the def is exited. If I include a print statement with the
increment it is printed.
Any suggestions are welcome.
The crux of the matter is this: the windows are (re)drawn in response
to events which instruct them to redraw themselves. The only way that
can happen is if the event loop is running.

When you have a loop in your code, while that loop is running the
event loop is _not_ running. This is especially bad if you put a sleep
in your code, because that causes the entire GUI to freeze. As a rule
of thumb you should never, ever use sleep in a GUI.

The quick fix for your problem is to add a call to `update_idletasks`
in your loop. Why `update_idletasks` instead of `update`? Because the
redrawing of windows is considered an "idle" task -- it is a class of
event that Tk will service when it is otherwise idle. That, and
calling `update` is potentially dangerous since it effectively creates
a new event loop nested inside the current event loop.

However, that's just a hack. The better solution is to architect your
code differently. If you have a long running process you should
consider running it in a separate thread or separate process. Even
better, if you can divide your work up into small chunks you can set
it up so that each chunk can be run during one iteration of the event
loop. You can request that Tkinter execute something during a future
iteration of the event loop with the `after` method.

Typically you do this with a function that does one chunk of work. It
then checks to see if there are any more chunks (by checking a flag,
or a list of data to be processed, etc) . If it finds there is more
work to do it uses itself as an argument to `after`, with a delay of a
few ms. That way, each time the event loop loops, it does one chunk of
your processing. No threads, no processes, no sleeps.

If you want to see an example of a countdown timer using this
technique see http://stackoverflow.com/a/10599462/7432
Paul Simon
2012-10-24 23:37:49 UTC
Permalink
Thanks very much for your response. What I wrote is just a very simple
script to familiarize myself with tkinter. I'm making a lot of mistakes and
so learning a lot :-)

The "sleep" command is in there so I can just see if the write loop is
running, using the "sleep" for the delay. I'm still working on figuring out
widget placement.

The entire program is a replacement of a MS Access app written in VBA, and
requires three parts. A gui (tkinter), data access using the serial port
with RS-485, and a simple database using sqlite. The latter two pieces
work, sort of, and am now working on the gui. The RS-485 interface needs
the sleep command or a do-while loop to wait for hardware turn around due to
the absence of hand shake in the serial interface.

I would be happy to keep you guys informed of my slow process ("life
interferes") if you wish. You can see the current implementation on my web
site, www.gophergulch.net under "temperature."
Paul
"Bryan Oakley" <bryan.oakley at gmail.com> wrote in message
Post by Bryan Oakley
Post by Paul Simon
I' m a novice python programmer and now starting to learn tkinter for a
front and db back end to replace an application written MS Access/VBA.
The
following program doesn't work as I expected as data is not written to the
text box until the def is exited. If I include a print statement with the
increment it is printed.
Any suggestions are welcome.
The crux of the matter is this: the windows are (re)drawn in response
to events which instruct them to redraw themselves. The only way that
can happen is if the event loop is running.
When you have a loop in your code, while that loop is running the
event loop is _not_ running. This is especially bad if you put a sleep
in your code, because that causes the entire GUI to freeze. As a rule
of thumb you should never, ever use sleep in a GUI.
The quick fix for your problem is to add a call to `update_idletasks`
in your loop. Why `update_idletasks` instead of `update`? Because the
redrawing of windows is considered an "idle" task -- it is a class of
event that Tk will service when it is otherwise idle. That, and
calling `update` is potentially dangerous since it effectively creates
a new event loop nested inside the current event loop.
However, that's just a hack. The better solution is to architect your
code differently. If you have a long running process you should
consider running it in a separate thread or separate process. Even
better, if you can divide your work up into small chunks you can set
it up so that each chunk can be run during one iteration of the event
loop. You can request that Tkinter execute something during a future
iteration of the event loop with the `after` method.
Typically you do this with a function that does one chunk of work. It
then checks to see if there are any more chunks (by checking a flag,
or a list of data to be processed, etc) . If it finds there is more
work to do it uses itself as an argument to `after`, with a delay of a
few ms. That way, each time the event loop loops, it does one chunk of
your processing. No threads, no processes, no sleeps.
If you want to see an example of a countdown timer using this
technique see http://stackoverflow.com/a/10599462/7432
Loading...