我已经重写了您的代码以删除一揽子导入(import *),使用类结构而不是全局变量和函数,并正确使用 tkinter mainloop 和 after 函数:
import tkinter as tk
import random
from math import pi, sin, cos
r1,r2,m1,m2 = 75,75,10,10
g = 9.81
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("Double Pendulum")
self.canvas = tk.Canvas(self, width=300, height=300)
self.canvas.pack()
self.delt=0.001
self.theta1 = random.random()*2*pi
self.theta2 = random.random()*2*pi
self.theta1_dot,self.theta2_dot = 0,0
self.dt = 0.1
self.t = 0
self.after(1, self.do_after)
def do_after(self):
self.canvas.delete('pendulum')
num1 = (-g*(2*m1+m2)*sin(self.theta1))
num2 = -m2*g*sin(self.theta1-2*self.theta2)
num3 = (-2*sin(self.theta1-self.theta2)*m2*(self.theta2_dot**2*r2+self.theta1_dot**2*r1*cos(self.theta1-self.theta2)))
denom1 = r1*(2*m1+m2-m2*cos(2*self.theta1-2*self.theta2))
theta1_dotdot = (num1 + num2 + num3)/denom1
num4 = 2*sin(self.theta1-self.theta2)
num5 = (self.theta1_dot**2*r1*(m1+m2))
num6 = g*(m1+m2)*cos(self.theta1)
num7 = self.theta2_dot**2*r2*m2*cos(self.theta1-self.theta2)
denom2 = r2*(2*m1+m2-m2*cos(2*self.theta1-2*self.theta2))
theta2_dotdot = (num4*(num5+num6+num7))/denom2
self.theta1_dot += theta1_dotdot * self.dt
self.theta2_dot += theta2_dotdot * self.dt
self.theta1 += self.theta1_dot * self.dt
self.theta2 += self.theta2_dot * self.dt
x1 = r1*sin(self.theta1)
y1 = r1*cos(self.theta1)
x2 = x1 + r2*sin(self.theta2)
y2 = y1 + r2*cos(self.theta2)
self.canvas.create_oval(150 + x2, 60 + y2, 150 + x2, 60 + y2, fill='black', outline='black', tag='trace')
self.canvas.create_line(150,60,150+x1, 60+y1,width=3,fill='pink', tags='pendulum')
self.canvas.create_line(150+x1, 60+y1,150+x2, 60+y2,width=3,fill='pink', tags='pendulum')
self.canvas.create_oval(140+x1,50+y1,160+x1,70+y1, fill='pink',outline='pink', tags='pendulum')
self.canvas.create_oval(140+x2,50+y2,160+x2,70+y2, fill='pink',outline='pink', tags='pendulum')
self.t += .1
self.after(1, self.do_after)
if __name__ == '__main__':
app = App()
app.mainloop()
在您的代码中,您强制调用update
循环的每次迭代,而不是让 tkinter 在需要更新时进行处理,您也在调用after
时没有回调,而 AFAICT 实际上并没有做任何事情。
我还在钟摆部件上添加了标签,这样您就可以通过一次调用将它们全部删除,而不必每次都存储它们的 ID。
经过进一步测试,真正的问题是您在画布上创建了数千个 tkinter 难以渲染的对象。要保留跟踪,您可以保留坐标列表并将其绘制为一条线:
import tkinter as tk
import random
from math import pi, sin, cos
r1,r2,m1,m2 = 75,75,10,10
g = 9.81
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("Double Pendulum")
self.canvas = tk.Canvas(self, width=300, height=300)
self.canvas.pack()
self.delt=0.001
self.theta1 = random.random()*2*pi
self.theta2 = random.random()*2*pi
self.theta1_dot,self.theta2_dot = 0,0
self.dt = 0.1
self.t = 0
self.trace_coords = []
self.after(1, self.do_after)
def do_after(self):
self.canvas.delete('trace')
self.canvas.delete('pendulum')
num1 = (-g*(2*m1+m2)*sin(self.theta1))
num2 = -m2*g*sin(self.theta1-2*self.theta2)
num3 = (-2*sin(self.theta1-self.theta2)*m2*(self.theta2_dot**2*r2+self.theta1_dot**2*r1*cos(self.theta1-self.theta2)))
denom1 = r1*(2*m1+m2-m2*cos(2*self.theta1-2*self.theta2))
theta1_dotdot = (num1 + num2 + num3)/denom1
num4 = 2*sin(self.theta1-self.theta2)
num5 = (self.theta1_dot**2*r1*(m1+m2))
num6 = g*(m1+m2)*cos(self.theta1)
num7 = self.theta2_dot**2*r2*m2*cos(self.theta1-self.theta2)
denom2 = r2*(2*m1+m2-m2*cos(2*self.theta1-2*self.theta2))
theta2_dotdot = (num4*(num5+num6+num7))/denom2
self.theta1_dot += theta1_dotdot * self.dt
self.theta2_dot += theta2_dotdot * self.dt
self.theta1 += self.theta1_dot * self.dt
self.theta2 += self.theta2_dot * self.dt
x1 = r1*sin(self.theta1)
y1 = r1*cos(self.theta1)
x2 = x1 + r2*sin(self.theta2)
y2 = y1 + r2*cos(self.theta2)
self.trace_coords.append((150 + x2, 60 + y2, 150 + x2, 60 + y2))
self.canvas.create_line(self.trace_coords, fill='black', tag='trace')
self.canvas.create_line(150,60,150+x1, 60+y1,width=3,fill='pink', tags='pendulum')
self.canvas.create_line(150+x1, 60+y1,150+x2, 60+y2,width=3,fill='pink', tags='pendulum')
self.canvas.create_oval(140+x1,50+y1,160+x1,70+y1, fill='pink',outline='pink', tags='pendulum')
self.canvas.create_oval(140+x2,50+y2,160+x2,70+y2, fill='pink',outline='pink', tags='pendulum')
self.t += .1
self.after(1, self.do_after)
if __name__ == '__main__':
app = App()
app.mainloop()