鉴于此代码
import tkinter
canvas = tkinter.Canvas()
canvas.pack()
i = 0
k = 1
while True:
canvas.create_text(100, 0+i, text="Python 3.6!", fill="red")
canvas.update()
canvas.create_rectangle(0, 0, canvas["width"], canvas["height"], fill=canvas["background"])
canvas.after(3)
i = i + k
if i==-1 or i==265:
k = -k
我们可以看到,在while循环的每个循环中,文本的移动速度变慢。
现在,由于我们每秒多次重新渲染整个画布,难怪它很慢。但是,为什么它会随着时间的推移而放慢?是因为大量的物体文字和矩形物体堆积在一起?这可以避免吗?
答案 0 :(得分:3)
不是移动文本,而是在每次迭代时创建一个新文本项和一个矩形来隐藏前一个文本项,因此画布变得拥挤而程序变慢。
有几种方法可以避免这种情况:
1)删除文本而不是将其隐藏在矩形后面:
text = canvas.create_text(100, i, text="Python 3.6!", fill="red")
...
canvas.delete(text)
2)使用coords
更改现有项目的坐标:
import tkinter
canvas = tkinter.Canvas()
canvas.pack()
i = 0
k = 1
text = canvas.create_text(100, i, text="Python 3.6!", fill="red")
while True:
canvas.coords(text, 100, i) # change coordinates of the text
canvas.update()
canvas.after(3)
i = i + k
if i==-1 or i==265:
k = -k
3)使用move
移动现有项目:
import tkinter
canvas = tkinter.Canvas()
canvas.pack()
i = 0
k = 1
text = canvas.create_text(100, i, text="Python 3.6!", fill="red")
while True:
canvas.move(text, 0, k) # increment by k the y coordinate of the text
canvas.update()
canvas.after(3)
i = i + k
if i==-1 or i==265:
k = -k
最后,您还可以使用after
方法制作动画,而不是使用while循环。类似的东西:
import tkinter
root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.pack()
def motion(i, k):
canvas.coords(text, 100, i)
i = i + k
if i==-1 or i==265:
k = -k
canvas.after(3, motion, i, k)
i = 0
k = 1
text = canvas.create_text(100, 0, text="Python 3.6!", fill="red")
motion(i, k)
root.mainloop()
答案 1 :(得分:1)
你的怀疑是正确的。重绘/渲染时间增加是因为您通过堆叠对象泄漏内存(它们在每次迭代时都没有消失,它们被保存在内存中)并且因为tkinter
在同一时间重绘它们。从那时起,我认为解决方案很明确。
当然可以避免。
有两个选项:
考虑这个例子:
import tkinter as tk
class App(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.canvas = tk.Canvas()
self.canvas.pack()
self.canvas.create_rectangle(0, 0, self.canvas["width"], self.canvas["height"], fill=self.canvas["background"])
self.text = self.canvas.create_text(100, 1, text="Python 3.6!", fill="red")
self.step = 3
self.simulate_things()
def simulate_things(self):
if 0 <= self.canvas.coords(self.text)[1] + self.step <= self.canvas.winfo_height():
# no need to change direction - still inside canvas
pass
else:
# switch direction
self.step *= -1
# you can use coords method as alternative
self.canvas.move(self.text, 0, self.step)
# scheduling next move
self.after(41, self.simulate_things)
if __name__ == '__main__':
app = App()
app.mainloop()
state
切换到hidden
/ disabled
(这也是删除对象的最佳方式,因为我们减少了{{ 1}} / id
管理到最低限度)。该选项会告诉item
不重绘它们。
但是,您需要跟踪已创建的对象以防止内存泄漏!考虑这个例子:
tkinter
正如您所看到的 - 管理性能的主要目标是减少重绘次数(并将对象数量保持在最低水平)。