使用 Tkinter 和 Matplotlib 配置实时图表轴

Configuring live graph axis with Tkinter and Matplotlib

我目前正在尝试使用 Tkinter 和 Matplotlib 在 window 上创建实时图表。此图表中的数据不断附加到 CSV 文件中,并像以下示例行一样保存:

2020/06/09 19:57:53,4,2.549,3.546

第二列是第二列,第 3 列和第 4 列是我试图绘制的关于时间的电压数据。我有一个单独的 python 脚本不断附加到此 CSV,因此它非常大并且有很多数据点。因此,一段时间后我的图表变得非常混乱(见下图),我想将数据限制为最近 60 秒的点,并让 x 轴的刻度间隔更大,而不是在每个数据点。我还想稍微缩小图表,这样噪声看起来就不那么明显了(例如,从 0 到 5 V)。我尝试添加 plot1.xlim(t-60, t), plot2.xlim(t-60, t), plot1.ylim(0,5), plot2.ylim(0,5)但其中 none 设置了我想要的限制。它只是放大了图表中一个非常奇怪的部分,垂直切掉了大部分图表。我应该如何配置我的图,使 y 轴从 0 变为 5,x 轴显示最近 60 秒的数据?我是 Tkinter 的新手,非常感谢任何帮助。谢谢!!!

我的屏幕图片轴真的很乱:

我的代码:

#import tkinter for GUI
import tkinter as tk
from tkinter import ttk
#font types
LARGE_FONT = ("Verdana", 12)

#import stuff for graph
import matplotlib
import matplotlib.ticker as mticker
from matplotlib import pyplot as plt
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure

#import animation to make graph live
import matplotlib.animation as animation
from matplotlib import style
style.use("seaborn-darkgrid")
#animate function
f = Figure(figsize=(20,20), dpi=100)
plot1 = f.add_subplot(211)
plot2 = f.add_subplot(212)
def animate(ii):
    pullData = open("/media/pi/68D2-7E93/test2.csv","r").read()
    dataList = pullData.split('\n')
    tList = []
    vList = []
    v1List = []
    for eachLine in dataList:
        if len(eachLine) >1:
            timedate, t, voltage, voltage1 = eachLine.split(',')
            tList.append(t)
            vList.append(voltage)
            v1List.append(voltage1)

    #plot graphs
    plot1.clear()
    plot1.plot(tList, vList, 'r')
    plot2.clear()
    plot2.plot(tList, v1List, 'b')
    #add labels and config axis
    plot1.set_title("Aquaponic Sensors")
    plot1.set_autoscaley_on(False)
    plot1.set_autoscalex_on(False)
    plot1.set_ylabel("pH (v)")
    #plot1.set_xlim(t-60,t)
    #plot1.axes.set_ybound(0,1)
    #plot1.set_ylim(2,4)
    #plot1.set_xlim(500, 510)

    plot2.set_ylabel("Temperature (v)")
    plot2.set_xlabel("Time (s)")
    #plot2.set_ybound(0,5)



#initialization
class AllWindow(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        #add title
        tk.Tk.wm_title(self, "NU Aquaponics")

        container = tk.Frame(self)      
        container.pack(side="top", fill="both", expand=True)      
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)      
        #show the frames
        self.frames = {}
        for F in (HomePage, ControlPanel, Settings):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(HomePage)

    def show_frame(self, cont):       
        frame = self.frames[cont]
        frame.tkraise()


#add home page
class HomePage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        label = tk.Label(self, text="Dashboard", font = LARGE_FONT)
        label.pack(pady=10, padx=10)

        #quit button
        quitButton = tk.Button(self, text="QUIT", fg='red',
                                command=quit)
        quitButton.pack()
        #navigation button
        navibutton1 = ttk.Button(self, text="Control Panel",
                            command=lambda: controller.show_frame(ControlPanel))
        navibutton1.pack()
        navibutton2 = ttk.Button(self, text="Settings",
                            command=lambda: controller.show_frame(Settings))
        navibutton2.pack()

        #add graph to dashboard

        #bring up canvas
        canvas = FigureCanvasTkAgg(f, self)
        canvas.draw()
        canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand = True)
        #add navigation bar
        toolbar = NavigationToolbar2Tk(canvas, self)
        toolbar.update()
        canvas._tkcanvas.pack()
        canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand = True)


#add control panel page
class ControlPanel(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Control Panel", font = LARGE_FONT)
        label.pack(pady=10, padx=10)

        #control buttons
        self.lightButton = tk.Button(self,
                             text="Light OFF",
                             bg= "red",
                             command=self.toggle_light)
        self.lightButton.pack()

        #navigation button
        navibutton1 = ttk.Button(self, text="Back to Dashboard",
                            command=lambda: controller.show_frame(HomePage))
        navibutton1.pack()
        navibutton2 = ttk.Button(self, text="Settings",
                            command=lambda: controller.show_frame(Settings))
        navibutton2.pack()

        #fcns triggered by control button
        #fcn to turn LED on or off
    def toggle_light(self):
      #  if LED1.value == 0:
     #       LED1.value = 1
        #change light button color
            self.lightButton.configure(bg= "green")
            self.lightButton.configure(fg= "white")
            self.lightButton.configure(text = "Light ON")
        else:
      #      LED1.value = 0
        #change light button color to red if light off
            self.lightButton.configure(bg= "red")
            self.lightButton.configure(text = "Light OFF")
#add settings page
class Settings(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Settings", font = LARGE_FONT)
        label.pack(pady=10, padx=10)
        #navigation button
        navibutton1 = ttk.Button(self, text="Back to Dashboard",
                            command=lambda: controller.show_frame(HomePage))
        navibutton1.pack()
        navibutton2 = ttk.Button(self, text="Go to Control Panel",
                            command=lambda: controller.show_frame(ControlPanel))
        navibutton2.pack()

app = AllWindow()
app.geometry('1025x690')
#update animation first
ani = animation.FuncAnimation(f, animate, interval=1000)
app.mainloop()

如果我取消注释 plot1.set_ylim(2,4) 行会发生这种情况,我是不是误解了 set_ylim 的作用?它似乎只是改变了显示的刻度数而不是缩小并设置最高和最低刻度 see image here

默认情况下,读取 CSV 文件将为您提供字符串。要修复您的代码,您必须将数据作为浮点数传递,例如:

    tList = []
    vList = []
    v1List = []
    for eachLine in dataList:
        if len(eachLine) >1:
            timedate, t, voltage, voltage1 = eachLine.split(',')
            tList.append(float(t))
            vList.append(float(voltage))
            v1List.append(float(voltage1))