Python Tkinter:如何为椭圆形对象留下痕迹

时间:2019-02-18 16:13:07

标签: python tkinter rendering tkinter-canvas

我有一个Python Tkinter代码,其中涉及利用引力吸引移动粒子。我正在为粒子使用create_oval函数,并且代码可以正常工作,但我希望粒子留下痕迹(不创建多个椭圆形对象,这会使代码变慢很多)。

代码如下:

import tkinter as tk
import ctypes

from numpy import sin as _s, cos as _c, tan as _t, arctan2, radians

sin = lambda x: round(_s(x),14)
cos = lambda x: round(_c(x),14)
tan = lambda x: round(_t(x),14)

sqrDist = lambda x1, y1, x2, y2: ((x2-x1)**2 + (y2-y1)**2)

s_width,s_height = ctypes.windll.user32.GetSystemMetrics(0),ctypes.windll.user32.GetSystemMetrics(1)

colours = [(255, 0, 0),(255, 165, 0),(255, 255, 0),(0, 255, 0),(0, 0, 255),(75, 0, 130),(240, 130, 240)]

class Particle:
    def __init__(self, x, y, ID, mass=1):
        self.x, self.y = x, y
        self.vx, self.vy = 0, 0
        self.mass = mass
        self.colour = colours[ID]
        self.id = cv.create_oval(x-10, y-10, x+10, y+10, width = 0, fill = "#%02x%02x%02x" % self.colour)

    def render(self):
        x , y = self.x , self.y
        cv.coords(self.id, [x-10,s_height-y+10,x+10,s_height-y-10])      

def exertGravity():
    for p1 in particles:
        ax, ay = 0, 0
        for p2 in particles:
            if (p1 is p2):
                continue
            mag = (p2.mass)/sqrDist(p1.x, p1.y, p2.x, p2.y)
            theta = arctan2(p2.y - p1.y, p2.x - p1.x)
            ax += mag*cos(theta)
            ay += mag*sin(theta)

        p1.vx += ax
        p1.vy += ay

esc = False

def escape(a):
    global esc
    esc = True

w = tk.Tk()
w.attributes("-fullscreen", True)
w.title('Particle Simulator')
w.geometry(str(s_width)+'x'+str(s_height)+"+0+0")
w.bind('<Escape>', escape)

cv = tk.Canvas(w, width=s_width, height=s_height)
cv.configure(background='black')
cv.pack()

p1 = Particle(960, 540, 0, 1)
p2 = Particle(960, 840, 1, 1)

p2.vx, p2.vy = -0.05,0

particles = [p1, p2]

while True:
    if esc: break

    exertGravity()        
    for p in particles:
        p.render()
        if p is p2:
            p.x += p.vx
            p.y += p.vy

    cv.update()

w.destroy()

0 个答案:

没有答案