On Wed, 20 Sep 2006 12:27:47 -0400 Michael M Haimes <[EMAIL PROTECTED]> wrote:
> ------------1---------- > Linux implementations of Python/Tkinter (the most current) seem to exhibit the > problem, but not Sun/Solaris or Windows. > > Essentially, I can't animate objects on a canvas without leaking memory at > about > 1Mb/s . I've tried 4 different methods, either deleting and redrawing objects, > or just moving objects, and either using Tk tags to label and operate the > objects, or storing their IDs in my program and operating with them that way. > I > can't think of any other way to do this, and I basically need to. I would try > the WCK to make my own, but the idea is to have the software run on a base > install of Python. > > The link to the four example test scripts I wrote up is here: > http://web.mit.edu/mhaimes/Public/tktest.tar > > ------------2---------- > The Mac OS X implementation of Python seems to exhibit this problem, and no > other systems. > > This problem is related to the above, namely, on the Mac animation seems to be > totally broken. Whenever Tk is running its event loop, it stops all other > python threads from processing and sits and waits for input. So my example > code > below runs a counter in a background thread which increments the number Tk has > displayed. On Windows/Linux, it just counts up until you press exit. On the > Mac, it will sit there and freeze if you aren't inputting anything, but as > soon > as you wave the mouse around or start typing it'll continue to increment; > whereas on Windows and Linux, the counter just counts up no matter what you > are > inputting. I know this could be done without two separate threads, but the > real > program that this is modelling an issue I'm having needs Tk to be in its event > loop, so that is not an option. > > Test code as follows: > ################# > import Tkinter > import thread > import sys > > app = Tkinter.Tk() > text = Tkinter.StringVar() > Tkinter.Label(app, textvariable = text).pack() > def looper(): > count = 0 > while 1: > text.set(`count`) > count+=1 > thread.start_new_thread(looper, ()) > Tkinter.Button(app, text="exit", command = sys.exit).pack() > app.mainloop() > ############## > > ----------------------- > > If anyone has any hints or suggestions for workarounds for either of the above > problems, it would be much appreciated. Or if you just run any of the test > programs on your systems and get different results than I predicted for you, > tell me some things about your system and what happened. > Hi Michael, for me (on linux) #2 works, on all examples of #1 i get this error: Unhandled exception in thread started by <function mover at 0xb7dbf684> Traceback (most recent call last): File "projekte/test2.py", line 18, in mover canvas.move(dot, -100*sin(t)*dt, 100*cos(t)*dt) File "/usr/lib/python2.4/lib-tk/Tkinter.py", line 2189, in move self.tk.call((self._w, 'move') + args) _tkinter.TclError: too many nested evaluations (infinite loop?) Generally I don't think it is a good idea to update Tk widgets directly from Python threads. I think you better create some variable to manage the communication between Tk and your child thread, as in this example which does practcally the same as #2: import Tkinter import thread import sys app = Tkinter.Tk() text = Tkinter.StringVar() Tkinter.Label(app, textvariable = text).pack() newtext = '0' def looper(): global newtext count = 0 while 1: #text.set(`count`) newtext = str(count) count+=1 thread.start_new_thread(looper, ()) Tkinter.Button(app, text="exit", command = sys.exit).pack() def update_label(): text.set(newtext) app.after(10, update_label) update_label() app.mainloop() And a working animation as in #1 with the same technique: import Tkinter from time import time, sleep from math import sin, cos from thread import start_new_thread import sys app = Tkinter.Tk() canvas = Tkinter.Canvas(app, width=300, height=300) canvas.pack() t = time() dot = canvas.create_oval(100*cos(t)+150, 100*sin(t)+150, 100*cos(t)+150, 100*sin(t)+150) x, y = 0, 0 def mover(): global x, y t = time() try: while 1: dt = time()-t;t=time() #canvas.move(dot, -100*sin(t)*dt, 100*cos(t)*dt) x, y = -100*sin(t)*dt, 100*cos(t)*dt sleep(0.1) except KeyboardInterrupt: sys.exit(-1) start_new_thread(mover, ()) def update_oval(): canvas.move(dot, x, y) canvas.after(100, update_oval) update_oval() app.mainloop() I hope this helps Michael _______________________________________________ Tkinter-discuss mailing list [email protected] http://mail.python.org/mailman/listinfo/tkinter-discuss
