Matplotlib和Tkinter实时图(AttributeError:'NoneType'对象在Tkinter回调中没有属性'update'异常)

时间:2018-09-12 07:18:32

标签: python matplotlib tkinter

我当前正在尝试绘制从“提交”按钮发送的数据,但是经过100次迭代后,程序给了我一个错误,但是如果我实现随机数就可以了,没有问题,你知道为什么会这样吗?那能给我吗,非常有用,谢谢和问候

import tkinter as tk
import time
import collections
import matplotlib, matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
matplotlib.use('TkAgg')
import matplotlib.animation as animation
import random


class Aplicacion():
    def __init__(self, plotLength = 100):
        self.raiz = tk.Tk()
        self.raiz.configure(bg = 'beige')
        self.raiz.title('Aplicación')

        self.plotMaxLength = plotLength
        self.data = collections.deque([0] * plotLength, maxlen=plotLength)
        self.plotTimer = 0
        self.previousTimer = 0

        self.entry = tk.Entry(self.raiz)
        self.entry.insert(0, '0')
        self.entry.pack(padx=5)
        SendButton = tk.Button(self.raiz, text='Send', command=self.send)
        SendButton.pack(padx=5)
        self.send()
        self.main()

    def send(self):
        self.val = self.entry.get()
        print(self.val)

    def tag1(self, frame, lines, lineValueText, lineLabel, timeText):

        currentTimer = time.clock()
        self.plotTimer = int((currentTimer - self.previousTimer) * 1000)
        self.previousTimer = currentTimer
        timeText.set_text('Muestreo = ' + str(self.plotTimer) + 'ms')

        value, = [self.val]
        #value = random.randint(1, 10)
        self.data.append(value)
        lines.set_data(range(self.plotMaxLength), self.data)
        lineValueText.set_text('[' + lineLabel + '] = ' + str(value))


    def main(self):

        maxPlotLength = 100
        xmin = 0
        xmax = maxPlotLength
        ymin = 0
        ymax = 10

        fig = plt.figure(figsize=(12, 6), dpi=70)
        ax = fig.add_subplot(111)
        ax.set_xlim(xmin, xmax)
        ax.set_ylim(ymin, ymax)
        ax.set_title('Control de Nivel')
        ax.set_xlabel("Tiempo")
        ax.set_ylabel("Variable de Control vs Variable de Proceso")

        lineLabel = 'Set Point (Litros)'
        timeText = ax.text(0.7, 0.95, '', transform=ax.transAxes)
        lines = ax.plot([], [], linewidth=1.0, label=lineLabel)[0]
        lineValueText = ax.text(0.7, 0.90, '', transform=ax.transAxes)
        plt.legend(loc="upper left")

        plt.grid(True)

        canvas = FigureCanvasTkAgg(fig, master=self.raiz)
        canvas.get_tk_widget().pack()
        anim = animation.FuncAnimation(fig, self.tag1, fargs=(lines, lineValueText, lineLabel, timeText),
                                       interval=10, blit=False)

        self.raiz.mainloop()


if __name__ == '__main__':
    Aplicacion()

1 个答案:

答案 0 :(得分:1)

最终会出现该错误,因为您是将字符串值附加到self.data中,并期望Matplotlib绘制这些字符串,但这样做无法做到。 (当然,该错误消息有些晦涩难懂。我只是通过向Matplotlib源文件中添加调试行来解决它的。)

您必须确保附加到self.data的值是数字,因此您需要将self.entry.get()的字符串值转换为数字,并处理该字符串不是有效数字的情况

最简单的方法是在您的send方法中。尝试将其替换为以下内容:

    def send(self):
        try:
            self.val = float(self.entry.get())
            print(self.val)
        except ValueError:
            messagebox.showwarning("Invalid number", "You entered an invalid number.  Please try again.")

您还需要添加行import tkinter.messagebox as messagebox。随时将错误消息翻译成另一种语言。