使用 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))
我目前正在尝试使用 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))