2012-11-22 44 views
0

使用下面的代码,随着小行星图像在屏幕上移动,内存使用量迅速增加,然后随着图像移出画布边缘而停止增加。谁能解释为什么会发生这种情况?我想保持一个图像在我的程序中无限期地在屏幕上移动,但它最终会占用我系统上的所有内存。Tkinter画布造成这种内存泄漏的原因是什么?

我是python,Tk和Tkinter的新手。有没有什么明显的我失踪了关于canvas.move(...)或canvas.update()?我应该用不同的方法来完成这项任务吗?谢谢。

from Tkinter import Tk, Canvas, Frame, BOTH, NW 
import Image 
import ImageTk 
from random import random 

root = Tk() 
f = Frame(root) 
f.pack(fill="both", expand=True) 
canvas = Canvas(f, width=1000, height=1000) 
canvas.pack(fill=BOTH, expand=1) 

image = ImageTk.PhotoImage(Image.open("asteroid01.png")) 
sprites = [] 
for i in range(10): 
    sprites.append(canvas.create_image(50*random(), 50*random(), image=image)) 


vel = {'x': 1, 'y': 1} 
while True: 
    for s in sprites: 
     canvas.move(s, vel['x'], vel['y']) 
    canvas.update() 

编辑:调用更新似乎是一个不好的做法,所以这里是代码更改建议。但是,该程序在图像移动时仍然消耗内存,直到窗口关闭才释放它。

from Tkinter import Tk, Canvas, Frame, BOTH, NW 
import Image 
import ImageTk 
from random import random 

root = Tk() 
f = Frame(root) 
f.pack(fill="both", expand=True) 
canvas = Canvas(f, width=1000, height=1000) 
canvas.pack(fill=BOTH, expand=1) 

image = ImageTk.PhotoImage(Image.open("asteroid01.png")) 
sprites = [] 
for i in range(10): 
    sprites.append(canvas.create_image(50*random(), 50*random(), image=image)) 

vel = {'x': 1, 'y': 1} 

def move(): 
    for s in sprites: 
     canvas.move(s, vel['x'], vel['y']) 
    canvas.after(10, move) 

move() 
root.mainloop() 

回答

0

我的猜测是因为你在紧密循环中调用更新。每次更新呼叫都有效地创建一个新的事件循环。这可能是吃掉你的记忆。

相反,改变你的逻辑看起来是这样的(未经测试,但应该是相当接近到右):

def move(): 
    for s in sprites: 
     canvas.move(s, vel['x'], vel['y']) 
    canvas.after(10, move) 
move() 

您拨打移动第一时间,那么它会导致自身的某个时候再次调用未来。数量的大小(以毫秒为单位)决定了对象移动的速度。

如果您希望能够停止动画,您可以设置一个标志,然后在每次调用after之前检查该标志。

+0

我仍然需要在move()内调用canvas.update(),虽然对吗?这样做我仍然有内存泄漏,即使在设置为1000之后。你能解释一下“事件循环”是什么意思吗? update()创建什么事件循环?我知道root.mainloop()将启动一个事件循环来寻找与窗口的交互。 canvas.update()不仅仅是重画画布吗? – user487100

+2

@ user487100:没有。作为一般的经验法则,你应该_不要叫'update'。不,'canvas.update()'不会更新画布。它创建了一个新的事件循环,就像'mainloop'一样。事件循环只是一个看起来像“while True:wait_for_event(); process_event()”的内部函数。当你调用'mainloop()'的时候,它会这样做,并且每次你调用'update()'的时候都会这样做,所以你最终会在一个循环内的一个循环内产生一个循环... –

+0

我没有意识到它不会重新调用update。我仍然看到内存泄漏。我会更新我在我的问题中使用的代码。你可以看一下吗? – user487100

相关问题