(Tkinter) 如何 运行 放置对象后的动画?
(Tkinter) How run an animation after put the object?
我正在尝试学习 tkinter,我发现了一个球的动画 (in this website)。
我试着修改成一个可以用鼠标放置的球。到目前为止,我已经完成了第一部分,但我不知道如何添加动作。我认为 canvas 需要在动画代码之前 运行 才能获取球坐标。
import tkinter
import time
animation_window_width=800
animation_window_height=600
animation_ball_radius = 30
animation_ball_min_movement = 5
animation_refresh_seconds = 0.01
def animate_ball(window, canvas, xinc, yinc, ball):
while True:
canvas.move(ball,xinc,yinc)
window.update()
time.sleep(animation_refresh_seconds)
ball_pos = canvas.coords(ball)
xl,yl,xr,yr = ball_pos
if xl < abs(xinc) or xr > animation_window_width-abs(xinc):
xinc = -xinc
if yl < abs(yinc) or yr > animation_window_height-abs(yinc):
yinc = -yinc
def position_ball(event):
ball = canvas.create_oval(event.x-animation_ball_radius,
event.y-animation_ball_radius,
event.x+animation_ball_radius,
event.y+animation_ball_radius,
fill="blue", outline="white", width=4)
window = tkinter.Tk()
window.title("Tkinter Animation Demo")
window.geometry(f'{animation_window_width}x{animation_window_height}')
canvas = tkinter.Canvas(window)
canvas.configure(bg="black")
canvas.pack(fill="both", expand=True)
ball=canvas.bind("<Button-1>", position_ball)
ball
#animate_ball(window, canvas, animation_ball_min_movement, animation_ball_min_movement, ball)
这是一个非常糟糕的例子。对于大多数 GUI,您不应该在 GUI 线程中使用带有 sleep()
的无限循环,因为它会阻塞 GUI 主循环(pygame 是一个明显的例外)。大多数 GUI,包括 tkinter,都是“事件驱动的”,你需要使用事件来做事。我想你想要的事件是鼠标移动。该事件将包含鼠标的 x、y 位置,所以剩下的就是将其传递给球。
import tkinter
animation_window_width=800
animation_window_height=600
animation_ball_radius = 30
animation_ball_min_movement = 5
animation_refresh_seconds = 0.01
def place_ball(event):
canvas.unbind("<Motion>") # stop responding to motion
canvas.xinc = animation_ball_min_movement
canvas.yinc = animation_ball_min_movement
animate_ball()
def locate_ball(event):
canvas.coords(ball,
event.x-animation_ball_radius,
event.y-animation_ball_radius,
event.x+animation_ball_radius,
event.y+animation_ball_radius)
# Create and animate ball in an infinite loop
def animate_ball(event=None):
canvas.move(ball,canvas.xinc,canvas.yinc) # move the ball
xl,yl,xr,yr = canvas.coords(ball) # get current coordinates
if xl < abs(canvas.xinc) or xr > animation_window_width-abs(canvas.xinc):
canvas.xinc = -canvas.xinc
if yl < abs(canvas.yinc) or yr > animation_window_height-abs(canvas.yinc):
canvas.yinc = -canvas.yinc
canvas.coords(ball, xl,yl,xr,yr) # set new coordinates
canvas.after(20, animate_ball) # set the loop event
window = tkinter.Tk()
window.title("Tkinter Animation Demo")
window.geometry(f'{animation_window_width}x{animation_window_height}')
canvas = tkinter.Canvas(window)
canvas.configure(bg="black")
canvas.pack(fill="both", expand=True)
ball = canvas.create_oval(0,0,0,0,fill="blue", outline="white", width=4)
canvas.bind('<Motion>', locate_ball)
canvas.bind('<Button-1>', place_ball)
window.mainloop()
我正在尝试学习 tkinter,我发现了一个球的动画 (in this website)。
我试着修改成一个可以用鼠标放置的球。到目前为止,我已经完成了第一部分,但我不知道如何添加动作。我认为 canvas 需要在动画代码之前 运行 才能获取球坐标。
import tkinter
import time
animation_window_width=800
animation_window_height=600
animation_ball_radius = 30
animation_ball_min_movement = 5
animation_refresh_seconds = 0.01
def animate_ball(window, canvas, xinc, yinc, ball):
while True:
canvas.move(ball,xinc,yinc)
window.update()
time.sleep(animation_refresh_seconds)
ball_pos = canvas.coords(ball)
xl,yl,xr,yr = ball_pos
if xl < abs(xinc) or xr > animation_window_width-abs(xinc):
xinc = -xinc
if yl < abs(yinc) or yr > animation_window_height-abs(yinc):
yinc = -yinc
def position_ball(event):
ball = canvas.create_oval(event.x-animation_ball_radius,
event.y-animation_ball_radius,
event.x+animation_ball_radius,
event.y+animation_ball_radius,
fill="blue", outline="white", width=4)
window = tkinter.Tk()
window.title("Tkinter Animation Demo")
window.geometry(f'{animation_window_width}x{animation_window_height}')
canvas = tkinter.Canvas(window)
canvas.configure(bg="black")
canvas.pack(fill="both", expand=True)
ball=canvas.bind("<Button-1>", position_ball)
ball
#animate_ball(window, canvas, animation_ball_min_movement, animation_ball_min_movement, ball)
这是一个非常糟糕的例子。对于大多数 GUI,您不应该在 GUI 线程中使用带有 sleep()
的无限循环,因为它会阻塞 GUI 主循环(pygame 是一个明显的例外)。大多数 GUI,包括 tkinter,都是“事件驱动的”,你需要使用事件来做事。我想你想要的事件是鼠标移动。该事件将包含鼠标的 x、y 位置,所以剩下的就是将其传递给球。
import tkinter
animation_window_width=800
animation_window_height=600
animation_ball_radius = 30
animation_ball_min_movement = 5
animation_refresh_seconds = 0.01
def place_ball(event):
canvas.unbind("<Motion>") # stop responding to motion
canvas.xinc = animation_ball_min_movement
canvas.yinc = animation_ball_min_movement
animate_ball()
def locate_ball(event):
canvas.coords(ball,
event.x-animation_ball_radius,
event.y-animation_ball_radius,
event.x+animation_ball_radius,
event.y+animation_ball_radius)
# Create and animate ball in an infinite loop
def animate_ball(event=None):
canvas.move(ball,canvas.xinc,canvas.yinc) # move the ball
xl,yl,xr,yr = canvas.coords(ball) # get current coordinates
if xl < abs(canvas.xinc) or xr > animation_window_width-abs(canvas.xinc):
canvas.xinc = -canvas.xinc
if yl < abs(canvas.yinc) or yr > animation_window_height-abs(canvas.yinc):
canvas.yinc = -canvas.yinc
canvas.coords(ball, xl,yl,xr,yr) # set new coordinates
canvas.after(20, animate_ball) # set the loop event
window = tkinter.Tk()
window.title("Tkinter Animation Demo")
window.geometry(f'{animation_window_width}x{animation_window_height}')
canvas = tkinter.Canvas(window)
canvas.configure(bg="black")
canvas.pack(fill="both", expand=True)
ball = canvas.create_oval(0,0,0,0,fill="blue", outline="white", width=4)
canvas.bind('<Motion>', locate_ball)
canvas.bind('<Button-1>', place_ball)
window.mainloop()