我正在制作一个 GUI,显示 4 个不同读数的图表。现在读数是随机生成的。我使用 matplotlib 和动画来显示实时读数,其中 2 个读数共享一个子图,另外两个显示在另一个子图上。在 x 轴上,我显示当前时间读数。
我对 python 比较陌生,所以我不确定其中一些东西是如何工作的。我的问题很可能是我有答案,但不知道如何应用它们。
这是我的代码:
import tkinter as tk
from tkinter import *
from tkinter import ttk
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import matplotlib.pyplot as plt #to plot the graph
import matplotlib.animation as animation #to create the real-time graph
from matplotlib import style #to change the way the graph will look
import matplotlib.ticker as mticker
import numpy as np
import datetime as dt
#-----------------------------END OF IMPORT -----------------------------------------------#
matplotlib.use("TkAgg") #backend of matplotlib??
style.use("dark_background")
LARGE_FONT = ("Times New Roman", 12)
NORM_FONT = ("Times New Roman", 9)
colors = ('tab:red','tab:blue')
#----------------------------------FUNCTION------------------------------------------------#
fig1 = plt.figure(0)
ax11 = fig1.add_subplot(211)
ax12 = ax11.twinx()
ax21 = fig1.add_subplot(212,sharex=ax11)
ax22 = ax21.twinx()
xList1= []
yList11=[]
yList12=[]
xList2= []
yList21=[]
yList22=[]
def animate_graph(i,x1,y11,y12,ax11
,ax12
,x2
,y21,y22,ax21,ax22
):
a = (2-1)*np.random.random()+1
b = (4-3)*np.random.random()+3
c = (6-5)*np.random.random()+5
d = (8-7)*np.random.random()+7
x1.append(dt.datetime.now().strftime('%H:%M:%S'))
y11.append(a)
y12.append(b)
x2.append(dt.datetime.now().strftime('%H:%M:%S'))
y21.append(c)
y22.append(d)
x1 = x1[-10:]
y11 = y11[-10:]
y12 = y12[-10:]
x2 = x2[-10:]
y21 = y21[-10:]
y22 = y22[-10:]
ax11.clear()
ln1 = ax11.plot(x1,y11,colors[0],label = 'Temp(C)')
ax11.tick_params(axis = 'y',labelcolor = colors[0])
ax12.clear()
ln2 = ax12.plot(x1,y12,colors[1],label = 'RH(%?)')
ax12.tick_params(axis = 'y',labelcolor = colors[1])
lns1 = ln1 + ln2
labs1 = [l.get_label() for l in lns1]
ax11.legend(lns1,labs1,bbox_to_anchor = (0,1.02,1,0.102),loc = 3,ncol = 3,borderaxespad = 0)
ax21.clear()
ln3 = ax21.plot(x2,y21,colors[0],label = 'CO(%)')
ax21.tick_params(axis = 'y',labelcolor = colors[0])
ax22.clear()
ln4 = ax22.plot(x2,y22,colors[1],label = 'CO2(%)')
ax22.tick_params(axis = 'y',labelcolor = colors[1])
lns2 = ln3 + ln4
labs2 = [l.get_label() for l in lns2]
ax21.legend(lns2,labs2,bbox_to_anchor = (0,1.02,1,0.102),loc = 3,ncol = 3,borderaxespad = 0)
ax11.tick_params(axis = 'x',labelrotation = 45)
ax21.tick_params(axis = 'x',labelrotation = 45)
#----------------------------------MAIN-------------------------------#
class main(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self,*args,**kwargs)
tk.Tk.title(self, "Hubba Dub")
container = tk.Frame(self)
container.pack(side = "top" , fill = "both" , expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0,weight = 1)
menubar = tk.Menu(self,tearoff=0)
filemenu = menubar.add_command(label= "Exit", command=quit)
menubar.add_cascade(label="File",menu= filemenu)
playpausemenu = menubar.add_command(label= "Pause", command=0)
menubar.add_cascade(label = "Pause/Play",menu=playpausemenu)
self.frames = {}
for f in (StartPage,GraphAll):
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,control):
tk.Frame.__init__(self,parent)
label = ttk.Label(self,text = "StartPage", font = LARGE_FONT)
label.pack(pady = 10, padx = 10)
b1 = ttk.Button(self,text = "Open page to display sensor data", command = lambda: control.show_frame(GraphAll))
b1.pack()
b3 = ttk.Button(self,text = "Exit", command = quit)
b3.pack()
class GraphAll(tk.Frame):
def __init__(self,parent,control):
tk.Frame.__init__(self,parent)
label = ttk.Label(self,text = "Show All Readings",font = LARGE_FONT)
label.pack()
b1 = ttk.Button(self,text = "Pause", command = lambda: anim.event_source.stop())
b1.pack()
b2 = ttk.Button(self,text = "Play", command = lambda: anim.event_source.start())
b2.pack()
b3 = ttk.Button(self,text = "Exit",command= quit)
b3.pack()
canvas = FigureCanvasTkAgg(fig1,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)
# call main class
gui = main()
# gui.geometry("1280x720")
gui.state('zoomed') #maximise window
anim = animation.FuncAnimation(fig1,animate_graph,
fargs=(xList1,yList11,yList12,ax11
,ax12
,xList2,yList21,yList22,ax21,ax22
)
,interval= 1000
)
#run in loop
gui.mainloop()
这是。您可以看到这里的读数显示正确。唯一的问题是 x 轴读数显示在两个而不是一个上。
我认为通过使用 sharex,它只会显示底部图上的 x 轴,而不是顶部图,但这并没有改变任何东西,这让我感到惊讶,因为这应该有效。
我尝试使用 set_xticks
set_xticks([])
但我没有看到任何变化。也许我做得不对,但我不确定问题到底出在哪里。
我从这个
问题中发现了
get_xticklines()
,但这似乎也不起作用。
如有任何帮助,我们将不胜感激。谢谢。
我发现了问题所在。所以事实证明,问题只是缺乏 Python 编程经验。
我正在关注sentdex的youtube播放列表来制作GUI。我在那里找到了问题的答案。
我在
plt.setp(ax21.get_xticklabels(),visible = False)
函数中添加了这一行 animate_graph
。代码块如下所示。
#setup second axis of plot 2
ax22.clear()
ln4 = ax22.plot(x2,y22,colors[1],label = 'CO2(%)')
ax22.tick_params(axis = 'y',labelcolor = colors[1])
#---------------------------------------------#
#set the x-axis tick labels visibility to False
plt.setp(ax21.get_xticklabels(),visible = False)
#----------------------------------------------#
#keep two legends from the two axes together. legends belong to an axis. In our case, we have two y-axis, so two separate legend made rather than together
lns2 = ln3 + ln4
labs2 = [l.get_label() for l in lns2]
ax21.legend(lns2,labs2,bbox_to_anchor = (0,-0.1,1,0)
# (0,1.02,1,0.102)
,loc = 'lower left',ncol = 3,borderaxespad = 0)
bbox_to_anchor
中的 ax21.legend()
参数应该更改为 (0,-0.1,1,0)
。现在我明白了
一切都按照我想要的方式进行。我很高兴:)