如何加速tkinter嵌入式matplot库和python
我有一个GUI,用于从arduino发送查询数据。然后,我没有放慢速度就开始实时绘制这些数据。我现在绘制的数字越来越多,速度越来越慢。当我第一次在matlab中编写这个GUI时,我遇到了类似的问题。我想知道我是否可以加快这一速度,因为我最终希望能够同时绘制多个窗口的图形。我从之前的建议中了解到动画库,但未能成功地使其在tkinter对象的生命中工作,据我所知,这是加速绘图的理想方法,除了直接绘制到画布之外。我一次只需要绘制大约200个数据点。以下是当前的GUI代码:如何加速tkinter嵌入式matplot库和python,python,user-interface,matplotlib,tkinter,tkinter-canvas,Python,User Interface,Matplotlib,Tkinter,Tkinter Canvas,我有一个GUI,用于从arduino发送查询数据。然后,我没有放慢速度就开始实时绘制这些数据。我现在绘制的数字越来越多,速度越来越慢。当我第一次在matlab中编写这个GUI时,我遇到了类似的问题。我想知道我是否可以加快这一速度,因为我最终希望能够同时绘制多个窗口的图形。我从之前的建议中了解到动画库,但未能成功地使其在tkinter对象的生命中工作,据我所知,这是加速绘图的理想方法,除了直接绘制到画布之外。我一次只需要绘制大约200个数据点。以下是当前的GUI代码: import Tkinter
import Tkinter
import numpy as np
import serial
import time
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from math import cos, sin
from collections import deque
class App:
def __init__(self, master):
frame = Tkinter.Frame(master)
self.Max_press = Tkinter.StringVar()
self.Max_press.set("10")
self.Min_press = Tkinter.StringVar()
self.Min_press.set("0")
self.Cycle_per_minute = Tkinter.StringVar()
self.Cycle_per_minute.set("12")
self.Duration_cycle = Tkinter.StringVar()
self.Duration_cycle.set("1")
self.respiration = Tkinter.LabelFrame(frame, text="Respiration
Testing", borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10)
self.respiration.grid(row=0, column=0, padx=20, pady=20)
self.max_pressure = Tkinter.Label(self.respiration, text="Maximum
Pressure (mmHg)")
self.max_pressure.grid(row=0, column=0, padx=5, pady=5)
self.Max_pressure =
Tkinter.Entry(self.respiration,textvariable=self.Max_press)
self.Max_pressure.grid(row=1, column=0, padx=5, pady=5)
self.min_pressure = Tkinter.Label(self.respiration, text="Minimum
Pressure (mmHg)")
self.min_pressure.grid(row=2, column=0, padx=5, pady=5)
self.Min_pressure = Tkinter.Entry(self.respiration,
textvariable=self.Min_press)
self.Min_pressure.grid(row=3, column=0, padx=5, pady=5)
self.cycles_per_minute = Tkinter.Label(self.respiration,
text="Cycles Per Minute")
self.cycles_per_minute.grid(row=4, column=0, padx=5, pady=5)
self.Cycles_per_minute =
Tkinter.Entry(self.respiration,textvariable=self.Cycle_per_minute)
self.Cycles_per_minute.grid(row=5, column=0, padx=5, pady=5)
self.duration_of_test = Tkinter.Label(self.respiration,
text="Duration (minutes)")
self.duration_of_test.grid(row=6, column=0, padx=5, pady=5)
self.Duration_of_test = Tkinter.Entry(self.respiration,
textvariable=self.Duration_cycle)
self.Duration_of_test.grid(row=7, column=0, padx=5, pady=5)
self.run_respiration = Tkinter.Button(self.respiration, text="RUN
RESPIRATION", command=self.getData)
self.run_respiration.grid(row=8, column=0, padx=5, pady=5)
self.burst = Tkinter.LabelFrame(frame, text="Burst Test",
borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 )
self.burst.grid(row=0, column=1, padx=20, pady=20)
self.burst_pressure = Tkinter.Button(self.burst, text="RUN BURST
TEST")
self.burst_pressure.grid(row=0, column=0, padx=5, pady=5)
self.test_options = Tkinter.LabelFrame(frame, text="Test Options",
borderwidth=10, relief=Tkinter.GROOVE, padx=10, pady=10 )
self.test_options.grid(row=0, column=2, padx=20, pady=35)
self.stop = Tkinter.Button(self.test_options, text="STOP", bd=10,
height=5, width=10)
self.stop.grid(row=0, column=0, padx=10, pady=25)
self.pause = Tkinter.Button(self.test_options, text="PAUSE", bd=10,
height=5, width=10)
self.pause.grid(row=1, column=0, padx=10, pady=25)
self.reset = Tkinter.Button(self.test_options, text="RESET", bd=10,
height=5, width=10)
self.reset.grid(row=2, column=0, padx=10, pady=25)
self.save = Tkinter.Button(self.test_options, text="SAVE", bd=10,
height=5, width=10)
self.save.grid(row=3, column=0, padx=10, pady=25)
self.xdata = deque([0]*200,maxlen=200)
self.ydata = deque([0]*200,maxlen=200)
self.fig = plt.Figure()
self.ax1 = self.fig.add_subplot(111)
self.line, = self.ax1.plot(self.xdata, self.ydata, lw=2)
self.canvas = FigureCanvasTkAgg(self.fig,master=master)
self.canvas.show()
self.canvas.get_tk_widget().grid(row=0, column=3, padx=20, pady=20)
frame.grid(row=0, column=0, padx=20, pady=20)
def getData(self):
press_max = float(self.Max_press.get())
press_min = float(self.Min_press.get())
duration = float(self.Duration_cycle.get())*60*20
cycle_time = float(self.Cycles_per_minute.get())
i = 0
x = []
y = []
amp = (press_max - press_min)/2
offset = amp + press_min
spb = 60/cycle_time
while (i < duration):
x.append(i)
sine = amp*np.sin((x[i]*(np.pi*4))/(2*spb)) + offset + 1
y.append(sine)
i = i + 1
arduinoData = serial.Serial('com5', 115200)
arduinoData.flushInput()
press = []
t = []
i = 0
start = time.time()
while (i < duration + 1):
while (arduinoData.inWaiting()==0):
pass
arduinoString = arduinoData.readline()
dataArray = int(arduinoString)
i = i + 1
print (dataArray)
self.plotData(dataArray,i)
end = time.time()
print (end - start)
def plotData(self, y, x ):
self.xdata.append(x)
self.ydata.append(y)
self.ax1.plot(self.xdata, self.ydata)
self.canvas.show()
root = Tkinter.Tk()
app = App(root)
root.mainloop()
导入Tkinter
将numpy作为np导入
导入序列号
导入时间
从matplotlib.backends.backend_tkagg导入图CAVASTKAGG
从matplotlib.figure导入图形
从matplotlib导入pyplot作为plt
将matplotlib.animation导入为动画
来自数学,因为,罪恶
从集合导入deque
类应用程序:
定义初始(自我,主):
帧=Tkinter.frame(主帧)
self.Max_press=Tkinter.StringVar()
自最大压力设置(“10”)
self.Min_press=Tkinter.StringVar()
自最小压力设置(“0”)
self.Cycle\u per\u minute=Tkinter.StringVar()
自我循环每分钟设置(“12”)
self.Duration\u cycle=Tkinter.StringVar()
自循环持续时间设置(“1”)
self.respiration=Tkinter.LabelFrame(frame,text=“respiration
测试“,边缘宽度=10,浮雕=Tkinter.GROOVE,padx=10,pady=10)
self.respiration.grid(行=0,列=0,padx=20,pady=20)
self.max_pressure=Tkinter.Label(自呼吸,text=“最大
压力(毫米汞柱)“)
自最大压力网格(行=0,列=0,padx=5,pady=5)
自身最大压力=
Tkinter.Entry(自我呼吸,文本变量=自我最大压力)
自最大压力网格(行=1,列=0,padx=5,pady=5)
自最小压力=Tkinter.标签(自呼吸,text=“最小
压力(毫米汞柱)“)
自最小压力网格(行=2,列=0,padx=5,pady=5)
自最小压力=Tkinter.入口(自呼吸,
textvariable=self.Min\u按)
自最小压力网格(行=3,列=0,padx=5,pady=5)
自我循环每分钟=Tkinter.标签(自我呼吸,
text=“每分钟循环数”)
每分钟自循环网格(行=4,列=0,padx=5,pady=5)
self.Cycles\u/u分钟=
Tkinter.Entry(自我呼吸,文本变量=自我循环每分钟)
每分钟自循环网格(行=5,列=0,padx=5,pady=5)
自我测试持续时间=Tkinter.标签(自我呼吸,
text=“持续时间(分钟)”)
测试网格的自持续时间(行=6,列=0,padx=5,pady=5)
自我测试的持续时间=进入(自我呼吸,
textvariable=self.Duration\u循环)
测试网格的自持续时间(行=7,列=0,padx=5,pady=5)
self.run\u respiration=Tkinter.Button(self.respiration,text=“运行
呼吸”,命令=self.getData)
self.run\u.grid(行=8,列=0,padx=5,pady=5)
self.burst=Tkinter.LabelFrame(frame,text=“突发测试”,
边框宽度=10,浮雕=Tkinter.GROOVE,padx=10,pady=10)
self.burst.grid(行=0,列=1,padx=20,pady=20)
self.burst\u pressure=Tkinter.按钮(self.burst,text=“运行爆破
测试“)
自破裂压力网格(行=0,列=0,padx=5,pady=5)
self.test_options=Tkinter.LabelFrame(frame,text=“测试选项”,
边框宽度=10,浮雕=Tkinter.GROOVE,padx=10,pady=10)
self.test\u options.grid(行=0,列=2,padx=20,pady=35)
self.stop=Tkinter.Button(self.test_选项,text=“stop”,bd=10,
高度=5,宽度=10)
self.stop.grid(行=0,列=0,padx=10,pady=25)
self.pause=Tkinter.Button(self.test_选项,text=“pause”,bd=10,
高度=5,宽度=10)
self.pause.grid(行=1,列=0,padx=10,pady=25)
self.reset=Tkinter.按钮(self.test_选项,text=“reset”,bd=10,
高度=5,宽度=10)
self.reset.grid(行=2,列=0,padx=10,pady=25)
self.save=Tkinter.Button(self.test\u选项,text=“save”,bd=10,
高度=5,宽度=10)
self.save.grid(行=3,列=0,padx=10,pady=25)
self.xdata=deque([0]*200,maxlen=200)
self.ydata=deque([0]*200,maxlen=200)
self.fig=plt.Figure()
self.ax1=self.fig.add_子批次(111)
self.line,=self.ax1.plot(self.xdata,self.ydata,lw=2)
self.canvas=FigureCanvasTkAgg(self.fig,master=master)
self.canvas.show()
self.canvas.get_tk_widget().grid(行=0,列=3,padx=20,pady=20)
frame.grid(行=0,列=0,padx=20,pady=20)
def getData(自):
press\u max=float(self.max\u press.get())
press\u min=float(self.min\u press.get())
持续时间=浮动(self.duration\u cycle.get())*60*20
cycle\u time=float(self.Cycles\u per\u minute.get())
i=0
x=[]
y=[]
放大器=(最大压力-最小压力)/2
偏移量=安培+按最小值
spb=60/循环时间
而(i self.fig = plt.Figure()
self.ax1 = self.fig.add_subplot(111)
self.line, = self.ax1.plot(self.xdata, self.ydata, lw=2)
self.canvas = FigureCanvasTkAgg(self.fig,master=master)
self.canvas.show()
self.canvas.get_tk_widget().grid(row=0, column=3, padx=20, pady=20)
frame.grid(row=0, column=0, padx=20, pady=20)
def getData(self):
press_max = float(self.Max_press.get())
press_min = float(self.Min_press.get())
duration = float(self.Duration_cycle.get())*60*20
cycle_time = float(self.Cycles_per_minute.get())
i = 0
x = []
y = []
amp = (press_max - press_min)/2
offset = amp + press_min
spb = 60/cycle_time
while (i < duration):
x.append(i)
sine = amp*np.sin((x[i]*(np.pi*4))/(2*spb)) + offset + 1
y.append(sine)
i = i + 1
arduinoData = serial.Serial('com5', 115200)
arduinoData.flushInput()
press = []
t = []
i = 0
start = time.time()
while (i < duration + 1):
while (arduinoData.inWaiting()==0):
pass
arduinoString = arduinoData.readline()
dataArray = int(arduinoString)
i = i + 1
print (dataArray)
self.plotData(dataArray,i)
end = time.time()
print (end - start)
def plotData(self, y, x ):
self.xdata.append(x)
self.ydata.append(y)
self.ax1.plot(self.xdata, self.ydata)
self.canvas.show()
root = Tkinter.Tk()
app = App(root)
root.mainloop()
import Tkinter as tk
import serial
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from collections import deque
import random
HISTORY_LEN = 200
class App(tk.Frame):
def __init__(self, master=None, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.running = False
self.ani = None
btns = tk.Frame(self)
btns.pack()
lbl = tk.Label(btns, text="Number of points")
lbl.pack(side=tk.LEFT)
self.points_ent = tk.Entry(btns, width=5)
self.points_ent.insert(0, '500')
self.points_ent.pack(side=tk.LEFT)
lbl = tk.Label(btns, text="update interval (ms)")
lbl.pack(side=tk.LEFT)
self.interval = tk.Entry(btns, width=5)
self.interval.insert(0, '30')
self.interval.pack(side=tk.LEFT)
self.btn = tk.Button(btns, text='Start', command=self.on_click)
self.btn.pack(side=tk.LEFT)
self.fig = plt.Figure()
self.ax1 = self.fig.add_subplot(111)
self.line, = self.ax1.plot([], [], lw=2)
self.canvas = FigureCanvasTkAgg(self.fig,master=master)
self.canvas.show()
self.canvas.get_tk_widget().pack()
def on_click(self):
if self.ani is None:
return self.start()
if self.running:
self.ani.event_source.stop()
self.btn.config(text='Un-Pause')
else:
self.ani.event_source.start()
self.btn.config(text='Pause')
self.running = not self.running
def start(self):
self.xdata = deque([], maxlen=HISTORY_LEN)
self.ydata = deque([], maxlen=HISTORY_LEN)
#~ self.arduinoData = serial.Serial('com5', 115200)
#~ self.arduinoData.flushInput()
self.points = int(self.points_ent.get()) + 1
self.ani = animation.FuncAnimation(
self.fig,
self.update_graph,
frames=self.points,
interval=int(self.interval.get()),
repeat=False)
self.running = True
self.btn.config(text='Pause')
self.ani._start()
def update_graph(self, i):
self.xdata.append(i)
#~ self.ydata.append(int(self.arduinoData.readline()))
self.ydata.append(random.randrange(100)) # DEBUG
self.line.set_data(self.xdata, self.ydata)
self.ax1.set_ylim(min(self.ydata), max(self.ydata))
self.ax1.set_xlim(min(self.xdata), max(self.xdata))
if i >= self.points - 1:
#~ self.arduinoData.close()
self.btn.config(text='Start')
self.running = False
self.ani = None
return self.line,
def main():
root = tk.Tk()
app = App(root)
app.pack()
root.mainloop()
if __name__ == '__main__':
main()