【发布时间】:2020-04-19 08:01:29
【问题描述】:
我正在尝试为回流炉控制器做简单的 GUI。 GUI 每 1 秒采样一次温度(现在它从随机函数中获取,最终从 arduino 获取)。但是现在每 1 秒内存使用量增加大约 3.5 mb - 我猜这与 matplot 动画有关,并且它只在旧图像之上绘制新图像(第 103-115 行)但是如何解决这个问题? 然后运行大约 385 秒:
C:\Users\veeti\PycharmProjects\Reflow\venv\Scripts\python.exe C:/Users/veeti/PycharmProjects/Reflow/Main.py Tkinter 中的异常 回调 Traceback(最近一次调用最后一次):文件“C:\ Program Files (x86)\python37\lib\tkinter__init__.py",第 1705 行,在 call 中 在 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", 第 118 行,在 _on_timer TimerBase._on_timer(self) 文件“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”, 第 1447 行,在 _step 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 行,平局 super(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", 第 399 行,在 get_renderer 中 self.renderer = RendererAgg(w, h, self.figure.dpi) 文件 "C:\Users\veeti\PycharmProjects\Reflow\venv\lib\site-packages\matplotlib\backends\backend_agg.py", 第 86 行,在 init 中 self._renderer = _RendererAgg(int(width), int(height), dpi) MemoryError: In RendererAgg: Out of memory
如果没有第 124 行命令“animate(1)”,动画也不会打开 - 为什么会这样?
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()
提前谢谢
【问题讨论】:
-
你能提供一个Minimal, Reproducible Example吗?
-
转载。仅供参考,我找到了this 并尝试了垃圾收集但没有成功。
-
看起来您正在构建画布并将其一遍又一遍地放置在旧画布之上,而不是更新它。那会导致你的记忆问题。解决方法是更新画布。
标签: python python-3.x matplotlib tkinter