在画布中模拟同时移动的物体

问题描述

我正在模拟天体系统中与 canvas.move 斗争。如何在定义的 Space 实例中同时移动多个对象?我想我必须对身体对象的身份做一些事情。但我查不出来。也许我应该使用重复绘制和删除方法而不是 canvas.move?请参阅下面代码的简化版本。有人有建议吗?非常感谢

import tkinter as tk

class Space(tk.Frame):
    def __init__(self,master,size,bg=None):
        super().__init__(master)
        frame = tk.Frame(master,border = 5)
        frame.pack()
        self.width,self.height = size[0],size[1]
        self.canvas = tk.Canvas(frame,width = self.width,height = self.height,borderwidth= 0,highlightthickness= 0,bg=bg)
        self.canvas.pack()

    def place_body(self,body):
        x1,y1 = body.loc[0],body.loc[1]
        x2,y2 = x1+body.size,y1+body.size
        self.canvas.create_oval(x1,y1,x2,y2,fill=body.color)

    def distance_step(self):
        pass

    def move_body(self,body):
        # in stead of distance_step:
        dx,dy = body.speed[0],body.speed[1]
        self.canvas.move(body,dx,dy)
        self.canvas.after(1,lambda: self.move_body(body))         

class CelestialBody:
    def __init__(self,name,mass,loc,speed,color="white"):
        self.name = name
        self.size = size
        self.mass = mass
        self.loc = loc
        self.speed = speed
        self.color = color

    def __repr__(self):
        return f"{self.name}"

class App:
    def __init__(self):
        x,y = 1000,800
        size = (x,y)
        space = Space(root,bg = 'black')         
        sun1_size = 30
        sun1_mass = 10
        sun1_loc = (700,450)        
        sun1_speed = (-200,0)
        
        sun2_size = 30
        sun2_mass = 10        
        sun2_loc = (300,350)
        sun2_speed = (200,0)       
       
        sun1 = CelestialBody("sun1",sun1_size,sun1_mass,sun1_loc,sun1_speed,color = "yellow")
        sun2 = CelestialBody("sun2",sun2_size,sun2_mass,sun2_loc,sun2_speed,color ="yellow")

        space.place_body(sun1)
        space.place_body(sun2)
        
        space.move_body(sun1)
        space.move_body(sun2)       

        print(sun1,sun2)
        root.mainloop()

root = tk.Tk()
root.title('UNIVERSE')
app = App()```

解决方法

您需要跟踪从 canvas.create_oval() 返回的标签。请参阅下面的 .tk_tag。我不得不放慢你的速度,因为物体立即离开了屏幕。另请注意:您可以只执行 dx,dy = body.speed[0],body.speed[1] 而不是 dx,dy = body.speed

import tkinter as tk


class Space(tk.Frame):
    def __init__(self,master,size,bg=None):
        super().__init__(master)
        frame = tk.Frame(master,border=5)
        frame.pack()
        self.width,self.height = size
        self.canvas = tk.Canvas(frame,width=self.width,height=self.height,borderwidth=0,highlightthickness=0,bg=bg)
        self.canvas.pack()

    def place_body(self,body):
        x1,y1 = body.loc
        x2,y2 = x1 + body.size,y1 + body.size
        body.tk_tag = self.canvas.create_oval(x1,y1,x2,y2,fill=body.color)

    def distance_step(self):
        pass

    def move_body(self,body):
        # in stead of distance_step:
        dx,dy = body.speed
        dx,dy = dx/100,dy/100
        self.canvas.move(body.tk_tag,dx,dy)
        self.canvas.after(1,lambda: self.move_body(body))


class CelestialBody:
    def __init__(self,name,mass,loc,speed,color="white"):
        self.name = name
        self.size = size
        self.mass = mass
        self.loc = loc
        self.speed = speed
        self.color = color
        self.tk_tag = None

    def __repr__(self):
        return f"{self.name}"


class App:
    def __init__(self):
        x,y = 1000,800
        size = (x,y)
        space = Space(root,bg='black')
        sun1_size = 30
        sun1_mass = 10
        sun1_loc = (700,450)
        sun1_speed = (-200,0)

        sun2_size = 30
        sun2_mass = 10
        sun2_loc = (300,350)
        sun2_speed = (200,0)

        sun1 = CelestialBody("sun1",sun1_size,sun1_mass,sun1_loc,sun1_speed,color="yellow")
        sun2 = CelestialBody("sun2",sun2_size,sun2_mass,sun2_loc,sun2_speed,color="yellow")

        space.place_body(sun1)
        space.place_body(sun2)

        space.move_body(sun1)
        space.move_body(sun2)

        print(sun1,sun2)
        root.mainloop()


root = tk.Tk()
root.title('UNIVERSE')
app = App()

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...