Tkinter .after()没有足够快地响应按键

时间:2017-06-09 15:07:44

标签: python tkinter tkinter-canvas

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

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()函数。但是,由于很多原因我无法使用它。

我主要担心的是屏幕更新所需的时间间隔。

2 个答案:

答案 0 :(得分:0)

根据我的理解,您希望能够使计时器保持一致,但也可以在计时器外的任何位置上下移动。

为了实现这一点,我将计时器移动到它自己的函数,并允许向上的函数调用对象的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()

答案 1 :(得分:0)

这都是数学。如果你想保持球以相同的速度移动同时更快地对按键做出反应,你可以多次调用更新两次,并将球移动一半。

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

顺便说一句,没有必要在每次迭代时删除并重新创建椭圆。可以在画布上移动项目。删除和重新创建最终会导致性能问题影响如何在内部实现画布。您创建的每个对象都会获得一个新的唯一ID,并且当它具有大量ID时,画布将变慢。画布不会重复使用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):
    ...