Мне наконец-то удалось заставить matplotlib в tkinter работать с живыми сюжетами.Мой проект читает 7 float для arduino каждые 100 мс (теоретически, на практике график слишком медленный, чтобы двигаться быстрее 250 мс) и отображать их на 7 различных графиках на странице графика.
У меня естьдомашняя страница на моем Tkinter, с кнопкой, связанной со страницей графика, и эта страница просто постоянно отображает новые данные.Проблема не в том, что она не может идти быстрее 250 мс, это было бы достаточно быстро для меня, скорее в том, что если я позволю моей программе работать некоторое время, например, 30 минут, она начнет становиться намного медленнее, например,возможность обновлять и получать новые данные только каждые 700 мс, а затем даже медленнее.Я предполагаю, что это связано с тем, что отображаемые данные становятся все больше и больше.
Вот код, который я использую:
f = Figure(figsize=(5,5), dpi=100)
ax=[]
lines=[0 for x in range(7)]
for i in range(0,7):
ax.append(f.add_subplot(4,2,1+i))
ax[i].set_autoscaley_on(True)
ax[i].set_autoscalex_on(True)
lines[i],=ax[i].plot([],[])
ser = serial.Serial('COM3', 115200) # Establish the connection on a specific port
Setup={"P_gain_X":0.0, "I_gain_X":0.0, "D_gain_X":0.0, "Set_point_X":0.0,
"P_gain_Y":0.0, "I_gain_Y":0.0, "D_gain_Y":0.0, "Set_point_Y":0.0,
"P_gain_Z":0.0, "I_gain_Z":0.0, "D_gain_Z":0.0, "Set_point_Z":0.0}
previous_time=datetime.datetime.now()
def update_line(hl, new_datax, new_datay):
hl.set_xdata(numpy.append(hl.get_xdata(), new_datax))
hl.set_ydata(numpy.append(hl.get_ydata(), new_datay))
def animate(i):
global previous_time
ser.write("R".encode('utf-8')) # send the command to arduino to receive the floats in return
time= datetime.datetime.now()
print ((time-previous_time)/1000) #just printing the time between 2 calls for debug
previous_time = time
for j in range(0,7):
new_value,=struct.unpack("<f",ser.read(4)) #get float from arduino
update_line(lines[j], time, new_value)
ax[j].relim()
ax[j].autoscale_view()
#mplcursors.cursor(lines[j])
f.canvas.draw()
f.canvas.flush_events()
class DisplayPID(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Display and change PID")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, GraphPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text=("""Welcome"""), font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Graph_Page",
command=lambda: controller.show_frame(GraphPage))
button1.pack()
class GraphPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Graph Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
canvas=FigureCanvasTkAgg(f,self)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
if __name__ == "__main__":
Start = DisplayPID()
ani = animation.FuncAnimation(f, animate, interval=100)
Start.mainloop()
Итак, первый вопрос: как я могу улучшитьдисплей так себе, что он не становится медленнее и медленнее или, по крайней мере, не так медленно.Зная, что я хочу быть в состоянии построить данные за несколько дней, а не минут.есть ли способ?Кроме того, как вы можете видеть в коде, я пытался использовать mplcursors.cursor (lines [j]), чтобы иметь возможность создать курсор, который будет следовать за мышью и отображать значения x и y.Но как только я воспользуюсь этим, как будто на несколько секунд запаздывает график, я не мог понять, почему он это делал?