简体   繁体   English

在 tkinter 画布中嵌入来自 Arduino 的 Matplotlib 实时绘图数据

[英]Embedding Matplotlib live plot data from Arduino in tkinter canvas

I've only been using Python for a couple of weeks.我才使用 Python 几个星期。 I have no problems plotting the data coming in from the Arduino with Matplotlib.我可以毫无问题地使用 Matplotlib 绘制来自 Arduino 的数据。 However the plot shows up as a pop-window and I would like that plot to only show up in a canvas in the root window of the GUI I'm making with tkinter.然而,该图显示为一个弹出窗口,我希望该图仅显示在我使用 tkinter 制作的 GUI 的根窗口中的画布中。 I've tried multiple combinations of things and I can't get it to work.我尝试了多种组合,但无法正常工作。 If I just add the plot values to the code, let's say:如果我只是将绘图值添加到代码中,比方说:

a.plot([1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7])

it works fine, so my main problem then is with the while loop when getting data from the Arduino.它工作正常,所以我的主要问题是从 Arduino 获取数据时的 while 循环。 I've also tried the drawnow option to update the plot but I get the same exact result.我也尝试了 drawnow 选项来更新情节,但我得到了完全相同的结果。 Whatever I do I can't seem to get the plot from to stop showing up as a separate window.无论我做什么,我似乎都无法从中获取情节以停止显示为单独的窗口。

Plot window with main GUI window in the back:后面带有主 GUI 窗口的绘图窗口:

后面有主 GUI 窗口的绘图窗口

Here's the sample code that I'm using:这是我正在使用的示例代码:

import serial
from tkinter import *
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg


root = Tk()
root.geometry('1200x700+200+100')
root.title('This is my root window')
root.state('zoomed')
root.config(background='#fafafa')


yar = []
plt.ion()
style.use('ggplot')
fig = plt.figure(figsize=(14, 4.5), dpi=100)
ax1 = fig.add_subplot(1, 1, 1)
ser = serial.Serial('com3', 9600)

def animate(i):
    while True:
        ser.reset_input_buffer()
        data = ser.readline().decode("utf-8")
        data_array = data.split(',')
        yvalue = float(data_array[1])
        yar.append(yvalue)
        print(yvalue)
        plt.ylim(0, 100)
        ax1.plot(yar, 'r', marker='o')
        plt.pause(0.0001)


plotcanvas = FigureCanvasTkAgg(fig, root, animate)
plotcanvas.get_tk_widget().grid(column=1, row=1)
ani = animation.FuncAnimation(fig, animate, interval=1000, blit=True)
plotcanvas.show()

root.mainloop()

The main loop of tk will take care of the animation, you therefore shouldn't use plt.ion() or plt.pause(). tk 的主循环将处理动画,因此您不应使用 plt.ion() 或 plt.pause()。

The animating function will be called every interval seconds.动画函数将每隔interval秒调用一次。 You cannot use a while True loop inside this function.您不能在此函数内使用while True循环。

There is no reason whatsoever to supply the animating function to the FigureCanvasTkAgg .没有任何理由为FigureCanvasTkAgg提供动画功能。

Don't use blit=True unless you know what you're doing.除非您知道自己在做什么,否则不要使用blit=True With an interval of one second this is anyways not necessary.以一秒的间隔,这无论如何是没有必要的。

Update the line instead of replotting it in every iteration step.更新线而不是在每个迭代步骤中重新绘制它。

#import serial
from Tkinter import *
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg


root = Tk()
root.geometry('1200x700+200+100')
root.title('This is my root window')
root.state('zoomed')
root.config(background='#fafafa')

xar = []
yar = []

style.use('ggplot')
fig = plt.figure(figsize=(14, 4.5), dpi=100)
ax1 = fig.add_subplot(1, 1, 1)
ax1.set_ylim(0, 100)
line, = ax1.plot(xar, yar, 'r', marker='o')
#ser = serial.Serial('com3', 9600)

def animate(i):
    #ser.reset_input_buffer()
    #data = ser.readline().decode("utf-8")
    #data_array = data.split(',')
    #yvalue = float(data_array[1])
    yar.append(99-i)
    xar.append(i)
    line.set_data(xar, yar)
    ax1.set_xlim(0, i+1)


plotcanvas = FigureCanvasTkAgg(fig, root)
plotcanvas.get_tk_widget().grid(column=1, row=1)
ani = animation.FuncAnimation(fig, animate, interval=1000, blit=False)

root.mainloop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM