Tkinter .after() 对按键的响应速度不够快

Tkinter .after() not responding to keypress fast enough

我正在尝试制作一个正在向前移动的球的动画。此外,如果用户按下向上或向下按钮,它应该分别移动。

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


class Movement:
    def __init__(self, _frame, _canvas):
        self.frame = _frame
        self.canvas = _canvas
        self.x = 10
        self.y = 150
        self.count = 0
        self.update()

        self.frame.bind_all("<Up>", lambda event: self.move_up())
        self.frame.bind_all("<Down>", lambda event: self.move_down())

        pass

    def move_up(self):
        self.y -= 10
        pass

    def move_down(self):
        self.y += 10
        pass



    def update(self):
        canvas.delete("obj")
        self.count += 10
        x2 = self.x + 50
        y2 = self.y + 50

        self.canvas.create_oval(self.x + self.count, self.y, x2 + self.count, y2, fill="red", tag="obj")

        root.after(1000, self.update)
        pass


root = tk.Tk()
width = 400
height = 400
canvas = tk.Canvas(root, width=width, height=height)
frame = tk.Frame(root, width=width, height=height)
if __name__ == '__main__':
    Movement(frame, canvas)
    canvas.grid()
    root.mainloop()

不过有一个问题。鉴于球每 1 秒移动一次,它对按键的响应速度不够快。因此,如果您单击上踢,屏幕会在一秒钟后更新。

我知道 Tkinter 中有一个 .move() 函数。但是,由于很多原因我不能使用它。

我主要关心的是屏幕更新的时间间隔。

据我了解,您希望能够使计时器保持一致向前移动,但也能够在计时器之外的任何时间点上下移动。

为了完成这个,我将计时器移到了它自己的函数中,并允许 up down 函数调用对象 destroy/create 函数。

我已更新您的代码以反映这一点。

看看这段代码,如果有帮助请告诉我。

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

class Movement:
    def __init__(self, _frame, _canvas):
        self.frame = _frame
        self.canvas = _canvas
        self.x = 10
        self.y = 150
        self.count = 0
        self.object_timer()

        self.frame.bind_all("<Up>",lambda event: self.move_up())
        self.frame.bind_all("<Down>",lambda event: self.move_down())

    def move_up(self):
        self.y -= 10
        self.update()

    def move_down(self):
        self.y += 10
        self.update()

    def update(self):
        canvas.delete("obj")
        x2 = self.x + 50
        y2 = self.y + 50
        self.canvas.create_oval(self.x + self.count, self.y, x2 + self.count, y2, fill="red", tag="obj")

    def object_timer(self):
        self.update()
        self.count += 10
        root.after(1000, self.object_timer)

root = tk.Tk()
width = 400
height = 400
canvas = tk.Canvas(root, width=width, height=height)
frame = tk.Frame(root, width=width, height=height)
if __name__ == '__main__':
    Movement(frame, canvas)
    canvas.grid()
    root.mainloop()

这只是数学。如果你想让球以相同的速度移动,同时对按键反应更快,你可以调用两倍的更新,并将球移动一半。

例如,不是每秒移动 10 个像素,而是每十分之一秒移动 1 个像素。最终结果仍然是每秒 10 个像素。动画会更流畅,对按键的反应也会更快。


顺便说一句,没有必要在每次迭代时都删除并重新创建椭圆。可以移动 canvas 上的项目。删除和重新创建最终会导致性能问题,这与 canvas 的内部实现方式有关。您创建的每个对象都会获得一个新的唯一 id,并且 canvas 在拥有大量 id 时会变慢。 canvas 不会重复使用 id。

我也建议不要使用 lambda。除非您需要它,否则它会增加复杂性而不会增加任何价值。只需在 move_upmove_down:

中添加一个额外的参数
self.frame.bind_all("<Up>",self.move_up)
self.frame.bind_all("<Down>", self.move_down)
...
def move_up(self, event=None):
    ...
def move_down(self, event=None):
    ...