My little brother is just getting into programming, and for his Science Fair project, he's doing a simulation of a flock of birds in the sky. He's gotten most of his code written, and it works nicely, but the birds need to move every moment.
Tkinter, however, hogs the time for its own event loop, and so his code won't run. Doing root.mainloop()
runs, runs, and keeps running, and the only thing it runs is the event handlers.
Is there a way to have his code run alongside the mainloop (without multithreading, it's confusing and this should be kept simple), and if so, what is it?
Right now, he came up with an ugly hack, tying his move()
function to <b1-motion>
, so that as long as he holds the button down and wiggles the mouse, it works. But there's got to be a better way.
Use the
after
method on theTk
object:Here's the declaration and documentation for the
after
method:When writing your own loop, as in the simulation (I assume), you need to call the
update
function which does what themainloop
does: updates the window with your changes, but you do it in your loop.Another option is to let tkinter execute on a separate thread. One way of doing it is like this:
Be careful though, multithreaded programming is hard and it is really easy to shoot your self in the foot. For example you have to be careful when you change member variables of the sample class above so you don't interrupt with the event loop of Tkinter.
This is the first working version of what will be a GPS reader and data presenter. tkinter is a very fragile thing with way too few error messages. It does not put stuff up and does not tell why much of the time. Very difficult coming from a good WYSIWYG form developer. Anyway, this runs a small routine 10 times a second and presents the information on a form. Took a while to make it happen. When I tried a timer value of 0, the form never came up. My head now hurts! 10 or more times per second is good enough for me. I hope it helps someone else. Mike Morrow
The solution posted by Bjorn results in a "RuntimeError: Calling Tcl from different appartment" message on my computer (RedHat Enterprise 5, python 2.6.1). Bjorn might not have gotten this message, since, according to one place I checked, mishandling threading with Tkinter is unpredictable and platform-dependent.
The problem seems to be that
app.start()
counts as a reference to Tk, since app contains Tk elements. I fixed this by replacingapp.start()
with aself.start()
inside__init__
. I also made it so that all Tk references are either inside the function that callsmainloop()
or are inside functions that are called by the function that callsmainloop()
(this is apparently critical to avoid the "different apartment" error).Finally, I added a protocol handler with a callback, since without this the program exits with an error when the Tk window is closed by the user.
The revised code is as follows: