【问题标题】:Modeling simultaneous moving bodies in canvas在画布中模拟同时移动的物体
【发布时间】:2020-12-20 19:09:43
【问题描述】:

我在模拟天体系统时遇到了 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, size, 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,size, 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()```

【问题讨论】:

    标签: python tkinter canvas orbital-mechanics


    【解决方案1】:

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

    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, size, 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, size, 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()
    

    【讨论】:

    • 这行得通。我现在明白您可以使用类对象的身份作为同一对象的属性。非常感谢格伦,Sjaak
    猜你喜欢
    • 2011-09-09
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多