尽管速度固定,为什么我的tkinter椭圆加速?

时间:2018-04-10 14:16:50

标签: python tkinter

我试图使用tkinter在这个画布上流畅地制作这个椭圆形移动,但是尽管有一个固定的速度,它似乎加速我移动它越多。即使在调试时我也注意到我的速度变量没有超过所需的值。我无法确定造成这种加速的原因,有人可以指出发生了什么吗?

这是我的代码:

from tkinter import*

window = Tk()
canvas = Canvas(window, width = 300, height = 300, bg ='white')
canvas.focus_set()

speedx = 0
speedy = 0
speed = 1

x1=40
y1=40

oval=canvas.create_oval(x1-10,y1-10,x1+10,y1+10,width=2,fill='orange')

def key_press(event):
    global x1, y1
    global speedx, speedy, speed

    button = event.keysym
    if button == 'Up':
        speedx = 0
        speedy = -speed
    elif button == 'Down':
        speedx = 0
        speedy = speed
    elif button == 'Right':
        speedx = speed
        speedy = 0
    elif button == 'Left':
        speedx = -speed
        speedy = 0
    move()

def move():
    global x1,y1
    global oval
    global speedx, speedy
    x1 += speedx
    y1 += speedy
    canvas.delete(oval)
    oval = canvas.create_oval(x1+10,y1-10,x1-10,y1+10,width=2,fill='orange')
    window.after(10, move)

def key_release(event):
    global speedx, speedy
    speedx = 0
    speedy = 0


canvas.bind('<KeyPress>', key_press)
canvas.bind("<KeyRelease>", key_release)
canvas.pack(padx =5, pady =5)
window.mainloop()

1 个答案:

答案 0 :(得分:1)

问题是,您可以在window.after(10, move)功能中拨打move,而不必再次取消它。对于每个move事件,这会为<KeyPress>生成一个永无止境的调用循环。

您可以做的是将after调用保存到变量中。有了这个,您可以确保不会从此循环外部再次调用move,此外,您可以使用它取消密钥发布时的after调用:

from tkinter import *

window = Tk()
canvas = Canvas(window, width = 300, height = 300, bg ='white')
canvas.focus_set()

speedx = 0
speedy = 0
speed = 1

# Make variable to store after call object
after_obj = None

x1=40
y1=40

oval=canvas.create_oval(x1-10,y1-10,x1+10,y1+10,width=2,fill='orange')

def key_press(event):
    global x1, y1
    global speedx, speedy, speed
    global after_obj
    button = event.keysym
    if button == 'Up':
        speedx = 0
        speedy = -speed
    elif button == 'Down':
        speedx = 0
        speedy = speed
    elif button == 'Right':
        speedx = speed
        speedy = 0
    elif button == 'Left':
        speedx = -speed
        speedy = 0
    # Only call move from here if there is no after scheduled
    if after_obj is None:
        move()

def move():
    global x1,y1
    global oval
    global speedx, speedy
    global after_obj
    x1 += speedx
    y1 += speedy
    canvas.delete(oval)
    oval = canvas.create_oval(x1+10,y1-10,x1-10,y1+10,width=2,fill='orange')
    # Save the after call object
    after_obj = window.after(10, move)

def key_release(event):
    global speedx, speedy  
    global after_obj
    # When pressing multiple buttons at the same time you can get a key release without an after_obj, so check if it exists then cancel it
    if after_obj:
        window.after_cancel(after_obj)
    # Reset after_obj to None so move can be called from key_press again
    after_obj = None
    speedx = 0
    speedy = 0


canvas.bind('<KeyPress>', key_press)
canvas.bind("<KeyRelease>", key_release)
canvas.pack(padx =5, pady =5)
window.mainloop()