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))

这会正确更新坐标。