Python Tkinter:如何让 canvas 每帧更新多边形坐标?
Python Tkinter : How do I get the canvas to update polygon coordinates every frame?
我正在做一个玩具项目来学习 tkinter 的基础知识。
我有一个无人机 class,它在 np.array
个对象中具有位置和速度,它会在每个增量更新自己。
位置是 0 和 1 之间的浮点数,然后乘以 height/width.
我现在想看到这个无人机在屏幕上移动,所以我使用了 window.after()
和 window.update()
方法。
这是我写的代码:
import tkinter as tk
import numpy as np
def update_drone(canv, drone):
# update the coords of all the polygon objects with new position (scaled to screen dimensions)
canv.coords(canv.find_withtag("drone"), *([WIDTH, HEIGHT] * drone.position))
def game_loop(window, canvas, dr):
delta = 0.01
# function which updates drone's attributes
dr.update(delta)
# built in sleep
sleep(delta)
#update drone function from above
update_drone(canvas, dr)
canvas.pack()
# if the drone isnt below the screen, call the game loop next delta
if dr.position[1] < 1:
window.after(int(delta * 1000), game_loop, window, canvas, dr)
if __name__ == "__main__":
# set up window
window = tk.Tk()
window.maxsize(WIDTH, HEIGHT)
window.minsize(WIDTH, HEIGHT)
window.configure(bg="black")
# height and width are global variables i define
canvas = tk.Canvas(window, bg="black", height=HEIGHT, width=WIDTH)
# create Drone object
dr = Drone()
# call draw drone function which is defined below
draw_drone(canvas, dr)
window.after(0, game_loop, window, canvas, dr)
# main loop
window.mainloop()
我上面调用的draw_drone
函数初始化了两个多边形:
def draw_drone(canv: tk.Canvas, drone: Drone) -> None:
pos_x, pos_y = WIDTH * drone.position[0], HEIGHT * drone.position[1]
# draw drone body
size = 20
canv.create_polygon(
[
pos_x - size,
pos_y - size,
pos_x - size,
pos_y + size,
pos_x + size,
pos_y + size,
pos_x + size,
pos_y - size,
],
outline="white",
fill="yellow",
width=3,
tags="drone",
)
canv.create_polygon(
[
pos_x,
pos_y + 0.8 * size,
pos_x - 0.8 * size,
pos_y,
pos_x,
pos_y - 0.8 * size,
pos_x + 0.8 * size,
pos_y,
],
outline="red",
fill="grey",
width=8,
tags="drone",
)
当我 运行 上面的代码时,游戏循环被调用(当我打印出无人机位置的值时,它们确实相应地更新了)但是 canvas 在第一个被冻结框架,永不更新。
如果有人能告诉我问题出在哪里,我将不胜感激!
编辑:
这是我使用的初级无人机class:
class Drone:
def __init__(self):
self.position = np.array([0.5, 0.5])
self.velocity = np.array([0, 0])
self.forces = np.array([0, 0])
def update(self, dt):
self.velocity = dt * (self.forces + np.array([0, 1])) # forces + gravity
self.position += self.velocity * dt
最后我的错误很简单。我不明白 canvas.coords
是如何工作的。我的 update_drone
函数的正确代码实际上是:
for t in canvas.find_withtag("drone"):
canv.coords(t, *([WIDTH, HEIGHT] * drone.position))
而不是
canv.coords(canv.find_withtag("drone"), *([WIDTH, HEIGHT] * drone.position))
这会正确更新坐标。
我正在做一个玩具项目来学习 tkinter 的基础知识。
我有一个无人机 class,它在 np.array
个对象中具有位置和速度,它会在每个增量更新自己。
位置是 0 和 1 之间的浮点数,然后乘以 height/width.
我现在想看到这个无人机在屏幕上移动,所以我使用了 window.after()
和 window.update()
方法。
这是我写的代码:
import tkinter as tk
import numpy as np
def update_drone(canv, drone):
# update the coords of all the polygon objects with new position (scaled to screen dimensions)
canv.coords(canv.find_withtag("drone"), *([WIDTH, HEIGHT] * drone.position))
def game_loop(window, canvas, dr):
delta = 0.01
# function which updates drone's attributes
dr.update(delta)
# built in sleep
sleep(delta)
#update drone function from above
update_drone(canvas, dr)
canvas.pack()
# if the drone isnt below the screen, call the game loop next delta
if dr.position[1] < 1:
window.after(int(delta * 1000), game_loop, window, canvas, dr)
if __name__ == "__main__":
# set up window
window = tk.Tk()
window.maxsize(WIDTH, HEIGHT)
window.minsize(WIDTH, HEIGHT)
window.configure(bg="black")
# height and width are global variables i define
canvas = tk.Canvas(window, bg="black", height=HEIGHT, width=WIDTH)
# create Drone object
dr = Drone()
# call draw drone function which is defined below
draw_drone(canvas, dr)
window.after(0, game_loop, window, canvas, dr)
# main loop
window.mainloop()
我上面调用的draw_drone
函数初始化了两个多边形:
def draw_drone(canv: tk.Canvas, drone: Drone) -> None:
pos_x, pos_y = WIDTH * drone.position[0], HEIGHT * drone.position[1]
# draw drone body
size = 20
canv.create_polygon(
[
pos_x - size,
pos_y - size,
pos_x - size,
pos_y + size,
pos_x + size,
pos_y + size,
pos_x + size,
pos_y - size,
],
outline="white",
fill="yellow",
width=3,
tags="drone",
)
canv.create_polygon(
[
pos_x,
pos_y + 0.8 * size,
pos_x - 0.8 * size,
pos_y,
pos_x,
pos_y - 0.8 * size,
pos_x + 0.8 * size,
pos_y,
],
outline="red",
fill="grey",
width=8,
tags="drone",
)
当我 运行 上面的代码时,游戏循环被调用(当我打印出无人机位置的值时,它们确实相应地更新了)但是 canvas 在第一个被冻结框架,永不更新。
如果有人能告诉我问题出在哪里,我将不胜感激!
编辑:
这是我使用的初级无人机class:
class Drone:
def __init__(self):
self.position = np.array([0.5, 0.5])
self.velocity = np.array([0, 0])
self.forces = np.array([0, 0])
def update(self, dt):
self.velocity = dt * (self.forces + np.array([0, 1])) # forces + gravity
self.position += self.velocity * dt
最后我的错误很简单。我不明白 canvas.coords
是如何工作的。我的 update_drone
函数的正确代码实际上是:
for t in canvas.find_withtag("drone"):
canv.coords(t, *([WIDTH, HEIGHT] * drone.position))
而不是
canv.coords(canv.find_withtag("drone"), *([WIDTH, HEIGHT] * drone.position))
这会正确更新坐标。