问题描述
我只使用Python几周了.使用Matplotlib绘制来自Arduino的数据时,我没有问题.但是,该图显示为弹出窗口,我希望该图仅显示在我使用tkinter制作的GUI的根窗口中的画布中.我尝试了多种组合,但无法正常工作.如果我只是将绘图值添加到代码中,可以这样说:
I've only been using Python for a couple of weeks. I have no problems plotting the data coming in from the Arduino with Matplotlib. 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. 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])
它工作正常,所以我的主要问题是从Arduino获取数据时的while循环.我也尝试了drawow选项来更新绘图,但得到的结果完全相同.无论我做什么,我似乎都无法阻止该图显示为一个单独的窗口.
it works fine, so my main problem then is with the while loop when getting data from the Arduino. I've also tried the drawnow option to update the plot but I get the same exact result. Whatever I do I can't seem to get the plot from to stop showing up as a separate window.
[绘图窗口,后面有主GUI窗口] [1]
[Plot window with main GUI window in the back][1]
这是我正在使用的示例代码:
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()
推荐答案
tk的主循环将处理动画,因此您不应使用plt.ion()或plt.pause().
The main loop of tk will take care of the animation, you therefore shouldn't use plt.ion() or plt.pause().
动画功能将每interval
秒调用一次.您不能在此函数内使用while True
循环.
The animating function will be called every interval
seconds. You cannot use a while True
loop inside this function.
没有任何理由向FigureCanvasTkAgg
提供动画功能.
There is no reason whatsoever to supply the animating function to the FigureCanvasTkAgg
.
除非您知道自己在做什么,否则请不要使用blit=True
.只要间隔一秒钟,就没有必要了.
Don't use blit=True
unless you know what you're doing. 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()
这篇关于将来自Arduino的Matplotlib实时绘图数据嵌入到tkinter canvas中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!