我写了这段非常简单的代码,可以在屏幕上移动一个椭圆:
from tkinter import *
""" GLOBAL VARS """
H, W = 400, 600 # default height / width
DELAY = 30 # frame rate in milliseconds
R = 20 # radius of the ball
class App:
def __init__(self, parent):
""" app init """
self.root = parent
self.canvas = Canvas(self.root, bg="white", height=H, width=W)
self.canvas.pack()
self.pos = [W / 2, H / 2] # starting position
self.speed = [2, 2] # x / y speed
self.canvas.create_oval(self.pos[0] - 20, self.pos[1] - 20, self.pos[0] + 20, self.pos[1] + 20, fill="blue")
self.loop()
def loop(self):
""" main loop """
coords = self.canvas.coords(1)[:2] # actual oval coordinates
if not 0 < coords[0] < W - 20: # the oval bounce off the window
self.speed[0] *= -1
if not 0 < coords[1] < H - 20:
self.speed[1] *= -1
self.canvas.move(1, *self.speed)
self.root.after(DELAY, self.loop)
""" GUI SETUP """
root = Tk()
App(root)
root.mainloop()
问题是,当我尝试增加帧速率时,椭圆形的一半消失了(我尝试截取一些屏幕截图,但是当我这样做时,应用程序卡住了一帧并且在屏幕截图中椭圆形正确显示,顺便说一句可以通过运行上面的代码自己尝试)。
我的问题是:是否有优化运动的方法,或者我是否必须接受 Tkinter 无法处理高 fps 的事实?
最佳答案
这就是我认为文档不足的地方 Tkinter performance issue .您看到一半椭圆消失的原因是,当检测到 Canvas 上要更新的内容时,它获得了 bbox。任何需要更新的东西,在你的例子中是椭圆形,然后只刷新 Canvas 的那部分(出于优化原因)。
但是,当您在 Canvas 上快速移动椭圆时,它会留下要更新的 Canvas 部分,这意味着椭圆的一部分将被截断,如您所见和描述的那样。
这是 Damage/Repair model .
在我看来,处理和解决这个问题的最简单方法是围绕您希望更新的内容创建一个更大的、(对用户而言)不可见的对象。这意味着 Tkinter 检测到较大的对象,并更新围绕它的小部件( Canvas )部分。诀窍是让新的更新部分包含您希望显示的内容,即椭圆形。
您可以通过 tag system 轻松移动较大的不可见物体和椭圆形.
要付诸实践,您可以添加 tag
的 "circle"
到你的椭圆形,然后用相同的标签创建一个新的椭圆形,但坐标覆盖整个椭圆形。指定 fill=""
也很重要和 outline=""
这样您就看不到新对象。
这看起来像:
self.canvas.create_oval(self.pos[0] - 20, self.pos[1] - 20,
self.pos[0] + 20, self.pos[1] + 20, fill="blue", tag="circle")
self.canvas.create_oval(self.pos[0] - 40, self.pos[1] - 40, self.pos[0] + 40,
self.pos[1] + 40, fill="", outline="", tag="circle")
第一个创建的椭圆是您当前带有标签的椭圆,第二个椭圆是不可见的更大的椭圆。
当你移动椭圆时,而不是移动 1
(这是你椭圆形的 ID,因为你先创建了它),你可以移动 "circle"
:
self.canvas.move("circle", *self.speed)
实现此操作后,您的椭圆不应显示任何截断点。如果你仍然看到截止点,那么你可以增加不可见椭圆的大小,例如60
的偏移量而不是 40
.
关于python - Tkinter:优化 Canvas 对象移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47000765/