Matplotlib в оптимизации скорости tkinter - PullRequest
0 голосов
/ 15 февраля 2019

Мне наконец-то удалось заставить 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.Но как только я воспользуюсь этим, как будто на несколько секунд запаздывает график, я не мог понять, почему он это делал?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...