4Manuals

  • PDF Cloud HOME

Tkinter + Matplot动画填充内存 Download

    如何将文本边界框与pyplot.Rectangle对齐? 导入类问题 在Python数据框中选择列时出错 使用Rabbit的pika确认消息 如何在按住键的同时暂停VideoStream? Python OpenCV 将我的代码从多处理更改为普通 TypeError:无法处理此数据类型 使用buildozer不会下载sdl2_image 如何从作为请求传递的输入类型数据绑定中提取数据 SMTPSenderRefused,421,超出超时

我正在尝试为回流炉控制器做简单的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)”,动画也不会打开-为什么会这样?

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 个答案:

答案 0 :(得分:3)

问题是您要一遍又一遍地堆叠画布。与其重新创建画布并像这样堆叠它们,我们不希望在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)

我已对您的代码进行了一些整理,以遵循PEP8标准。见下文:

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

接近动画开始的内存:

enter image description here

1分钟后再进行存储:

enter image description here

如您所见,内存增长已停止,不再超过3 MB /秒。

至于需要使用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()来了解一切。我什至无法在这里推测,因此其他人将不得不回答这一部分。



Similar searches
    如何在Blazor服务器中设置同意cookie 如果在MySQL中进行交换,如何删除具有两个相同列值的行 如何获取avfoundation uiview以将视频保存在imagevewivew上 DataTables使用现有数据折叠行 如何设置页面参数Twitter API用户时间轴