我正在尝试为回流炉控制器做简单的GUI。
GUI每1秒对温度采样一次(现在它是从随机函数中获取的,最终是从arduino获取的)。但是现在每1秒ram的使用量增加约3.5 mb-我想这与matplot动画有关,它只在旧图像上绘制新图像(第103-115行),但是如何解决呢?
然后运行aprox 385秒: C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ Scripts \ python.exe
Tkinter中的C:/Users/veeti/PycharmProjects/Reflow/Main.py异常
回调回溯(最近一次呼叫最近):文件“ C:\ Program Files
(x86)\ python37 \ lib \ tkinter__init __。py“,第1705行,在调用中
在callit中返回self.func(* args)文件“ C:\ Program Files(x86)\ python37 \ lib \ tkinter__init __。py”,行749
func(* args)文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ backends_backend_tk.py”,
_on_timer中的第118行
TimerBase._on_timer(自己)文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ backend_bases.py”,
第1194行,在_on_timer中
ret = func(* args,** kwargs)文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ animation.py”,
_step中的第1447行
still_going = Animation._step(self,* args)文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ animation.py”,
第1173行,在_step中
self._draw_next_frame(framedata,self._blit)文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ animation.py”,
第1192行,在_draw_next_frame中
self._draw_frame(framedata)文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ animation.py”,
第1755行,在_draw_frame中
self._drawn_artists = self._func(framedata, self._args)文件“ C:/Users/veeti/PycharmProjects/Reflow/Main.py”,第115行,带有动画
canvas.draw()文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ backends \ backend_tkagg.py”,
第9行,平局
超级(FigureCanvasTkAgg,self).draw()文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ backends \ backend_agg.py”,
386行,平局
self.renderer = self.get_renderer(cleared = True)文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ backends \ backend_agg.py”,
get_renderer中的第399行
self.renderer = RendererAgg(w,h,self.figure.dpi)文件“ C:\ Users \ veeti \ PycharmProjects \ Reflow \ venv \ lib \ site-packages \ matplotlib \ backends \ backend_agg.py”,
第86行,初始化
self._renderer = _RendererAgg(int(width),int(height),dpi)MemoryError:在RendererAgg中:内存不足 如果没有第124行的命令“ animate(1)”,动画也不会打开-为什么会这样? 提前 答案 0 :(得分:3) 问题是您要一遍又一遍地堆叠画布。与其重新创建画布并像这样堆叠它们,我们不希望在 解决方法是更改此内容 对此: 我已对您的代码进行了一些整理,以遵循PEP8标准。见下文: 接近动画开始的内存: 1分钟后再进行存储: 如您所见,内存增长已停止,不再超过3 MB /秒。 至于需要使用
import tkinter
import matplotlib.pyplot as plt
import random
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg)
def exitHandler():
print("at exit handler")
ani.event_source.stop()
root.destroy()
def startButtonClick():
print("start")
def stopButtonClick():
print("stop")
def readTemperature():
return random.randint(0,250)
def updateTimeLabel(time = -99):
timeLabel.config(text= "Time: {}".format (time))
def updateTargetTempLabel(temp = -99) :
targetTempLabel.config(text="Target temp: \n {} ".format (temp))
def updateCurrentTempLabel(temp = -99) :
currentTempLabel.config(text="Current temp: \n {} ".format (temp))
def updateHeaterStatus(temp,target):
if (temp < target):
heaterStatusLabel.config(text="Heater: \n On")
else:
heaterStatusLabel.config(text="Heater: \n Off")
def calculateTarget(time):
global timePoints, tempQuidance, targetTemp
#find current slope and calculate the target temp
for i in range (len(timePoints)):
if (timePoints[i] < time < timePoints[i+1]):
slope = (tempQuidance[i+1] - tempQuidance[i]) / (timePoints[i+1] -timePoints[i])
currentTarget = (time -timePoints[i]) * slope + tempQuidance[i]
return (currentTarget)
def animate(i):
global timePoints,tempQuidance,numberOfPoints,measuredTemp, time
time = time+1
measuredTemp.append(readTemperature())
numberOfPoints.append(len(measuredTemp))
ax.clear()
ax.plot(timePoints,tempQuidance)
ax.plot(numberOfPoints,measuredTemp)
updateTimeLabel(time)
updateTargetTempLabel(calculateTarget(time))
updateCurrentTempLabel(measuredTemp[-1])
updateHeaterStatus(measuredTemp[-1], 100)
canvas = FigureCanvasTkAgg(fig,plotFrame)
canvas.draw()
canvas.get_tk_widget().grid(row=3,column=0,columnspan = 4)
global measuredTemp, numberOfPoints, time, targetTemp
time = 0
measuredTemp=[]
numberOfPoints=[]
targetTemp = 0
#temperature profile
timePoints = [0,300,400,460,500]
tempQuidance =[0,150,150,250,0]
root=tkinter.Tk()
root.title('Reflow oven controller')
root.geometry("1600x800")
controlFrame = tkinter.LabelFrame(root,width = 500, height = 800, borderwidth = 3, padx=5,pady=5)
plotFrame = tkinter.LabelFrame(root,padx=5,pady=5)
controlFrame.grid(row = 0, column = 0 )
controlFrame.grid_propagate(0)
plotFrame.grid(row = 0, column= 1)
timeLabel=tkinter.Label(plotFrame,text = "Time: ")
targetTempLabel = tkinter.Label(plotFrame,text = "Target temp")
currentTempLabel = tkinter.Label(plotFrame,text = "Current temp")
heaterStatusLabel = tkinter.Label(plotFrame,text = "Heater status: \n unknown")
timeLabel.grid(row= 0, column=0)
targetTempLabel.grid(row=0, column= 1)
currentTempLabel.grid(row=0, column= 2)
heaterStatusLabel.grid(row = 0, column = 3)
fig=plt.figure()
ax = fig.add_subplot(1, 1, 1)
startButton = tkinter.Button(controlFrame, text = "Start", command = startButtonClick)
stopButton = tkinter.Button(controlFrame, text="Stop", command = stopButtonClick)
startButton.grid(row = 0,column = 0)
stopButton.grid(row = 0 ,column= 1 )
animate(1)
ani = animation.FuncAnimation(fig, animate, interval=1000) #run animation every 1s, animate func takes care of getting new values and GUI update
root.protocol("WM_DELETE_WINDOW", exitHandler)
root.mainloop()
1 个答案:
Error in [.data.frame (data, , all.vars(Terms), drop = FALSE) :
undefined columns selected
函数外部创建画布,然后将draw留在函数中。animate
fig=plt.figure()
ax = fig.add_subplot(1, 1, 1)
def animate(i):
global timePoints,tempQuidance,numberOfPoints,measuredTemp, time
time = time+1
measuredTemp.append(readTemperature())
numberOfPoints.append(len(measuredTemp))
ax.clear()
ax.plot(timePoints,tempQuidance)
ax.plot(numberOfPoints,measuredTemp)
updateTimeLabel(time)
updateTargetTempLabel(calculateTarget(time))
updateCurrentTempLabel(measuredTemp[-1])
updateHeaterStatus(measuredTemp[-1], 100)
canvas = FigureCanvasTkAgg(fig,plotFrame)
canvas.draw()
canvas.get_tk_widget().grid(row=3,column=0,columnspan = 4)
fig=plt.figure()
ax = fig.add_subplot(1, 1, 1)
canvas = FigureCanvasTkAgg(fig,plotFrame)
canvas.get_tk_widget().grid(row=3,column=0,columnspan = 4)
def animate(i):
global timePoints,tempQuidance,numberOfPoints,measuredTemp, time
time = time+1
measuredTemp.append(readTemperature())
numberOfPoints.append(len(measuredTemp))
ax.clear()
ax.plot(timePoints,tempQuidance)
ax.plot(numberOfPoints,measuredTemp)
updateTimeLabel(time)
updateTargetTempLabel(calculateTarget(time))
updateCurrentTempLabel(measuredTemp[-1])
updateHeaterStatus(measuredTemp[-1], 100)
canvas.draw()
import tkinter as tk
import matplotlib.pyplot as plt
import random
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
def exit_handler():
print("at exit handler")
ani.event_source.stop()
root.destroy()
def start_button_click():
print("start")
def stop_button_click():
print("stop")
def read_temperature():
return random.randint(0, 250)
time = 0
measured_temp = []
number_of_points = []
targetTemp = 0
time_points = [0, 300, 400, 460, 500]
temp_quidance = [0, 150, 150, 250, 0]
root = tk.Tk()
root.title('Reflow oven controller')
root.geometry("1600x800")
control_frame = tk.LabelFrame(root, width=500, height=800, borderwidth=3, padx=5, pady=5)
plot_frame = tk.LabelFrame(root, padx=5, pady=5)
control_frame.grid(row=0, column=0)
control_frame.grid_propagate(0)
plot_frame.grid(row=0, column=1)
time_label = tk.Label(plot_frame, text="Time: ")
target_temp_label = tk.Label(plot_frame, text="Target temp")
current_temp_label = tk.Label(plot_frame, text="Current temp")
heater_status_label = tk.Label(plot_frame, text="Heater status: \n unknown")
time_label.grid(row=0, column=0)
target_temp_label.grid(row=0, column=1)
current_temp_label.grid(row=0, column=2)
heater_status_label.grid(row=0, column=3)
def update_time_label(time=-99):
time_label.config(text="Time:\n{}".format(time))
def update_target_temp_label(temp=-99):
target_temp_label.config(text="Target temp:\n{}".format(temp))
def update_current_temp_label(temp=-99) :
current_temp_label.config(text="Current temp:\n{}".format(temp))
def update_heater_status(temp, target):
if temp < target:
heater_status_label.config(text="Heater:\nOn")
else:
heater_status_label.config(text="Heater:\nOff")
def calculate_target(time):
for i in range(len(time_points)):
if time_points[i] < time < time_points[i+1]:
slope = (temp_quidance[i+1] - temp_quidance[i]) / (time_points[i+1] - time_points[i])
current_target = (time - time_points[i]) * slope + temp_quidance[i]
return current_target
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
canvas = FigureCanvasTkAgg(fig, plot_frame)
canvas.get_tk_widget().grid(row=3, column=0, columnspan=4)
def animate(_=None):
global time
time = time+1
measured_temp.append(read_temperature())
number_of_points.append(len(measured_temp))
ax.clear()
ax.plot(time_points, temp_quidance)
ax.plot(number_of_points, measured_temp)
update_time_label(time)
update_target_temp_label(calculate_target(time))
update_current_temp_label(measured_temp[-1])
update_heater_status(measured_temp[-1], 100)
canvas.draw()
start_button = tk.Button(control_frame, text="Start", command=start_button_click)
stop_button = tk.Button(control_frame, text="Stop", command=stop_button_click)
start_button.grid(row=0, column=0)
stop_button.grid(row=0, column=1)
animate()
ani = animation.FuncAnimation(fig, animate, interval=1000)
root.protocol("WM_DELETE_WINDOW", exit_handler)
root.mainloop()
来启动动画,我不是100%肯定的。我还没有足够的animate()
来了解一切。我什至无法在这里推测,因此其他人将不得不回答这一部分。