Quantcast
Channel: Active questions tagged python - Stack Overflow
Viewing all articles
Browse latest Browse all 23131

Control real-time animations from a menubar but only the page in the foreground

$
0
0

I am working with matplotlib and tkinter in Raspberry pi 4B. I have three different sensor readings shown in real-time. My goal is to pick a sensor from the menubar, which would open the corresponding page. In the page, I would just have a blank graph. From the start/stop menu, I will start reading, which would start displaying the readings right away. I will also stop the animation from the menu.

Issue:

  1. I noticed that the animations are running in background. I am not sure how to stop that.
  2. I don't know how to program the start and stop option in the menubar to control the current graph.
  3. I am not sure how to modify my function animate_graph that reads the frame that called it. This seems more of a simple issue, but I don't know what parameter I should pass to this function.

Here is my code:

import tkinter as tk from tkinter import *from tkinter import ttkimport matplotlib matplotlib.use("TkAgg") #backend of matplotlib??from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tkfrom matplotlib.figure import Figure #figure we call to format the gaphimport matplotlib.pyplot as plt #to plot the graphimport matplotlib.animation as animation #to create the real-time graphfrom matplotlib import style #to change the way the graph will lookstyle.use("dark_background") import numpy as npimport datetime as dt#-----------------------------END OF IMPORT -----------------------------------------------#LARGE_FONT = ("Times New Roman", 12)NORM_FONT = ("Times New Roman", 9)#----------------------------------FUNCTION------------------------------------------------#def popupmsg(title, msg):    popup = tk.Tk()    popup.wm_title(title)    label = ttk.Label(popup,text = msg, font = NORM_FONT)    label.pack(side = "top",fill = "x",pady = 10)    b1 = ttk.Button(popup,label = "Okay", command=popup.destroy)    b1.pack()    popup.mainloop()fig_s1,ax1_s1 = plt.subplots() ax2_s1 = ax1_s1.twinx()x_s1 = []y1_s1 = []y2_s1 = []def animate_graph(i,x,y1,y2,ax1,ax2): #add frame here    reading1,reading2 = (5-3) * np.random.random() + 3,(5-3) * np.random.random() + 3    #append xs and ys with time and temp respectively    x.append(dt.datetime.now().strftime('%H:%M:%S'))    y1.append(reading1)    y2.append(reading2)    #limit xs and ys to the last 10 seconds    x = x[-10:]    y1 = y1[-10:]    y2 = y2[-10:]    #Draw x and y lists    #y-axis for temperature    color = 'tab:red'    ax1.clear()    ln1= ax1.plot(x,y1,color = color, linestyle = 'dashed', label = 'Read1')    ax1.tick_params(axis = 'y', labelcolor = color)    #y-axis for relative humidity    color = 'tab:blue'    ax2.clear()    ln2 = ax2.plot(x,y2,color = color,label = 'Read2')    ax2.tick_params(axis = 'y', labelcolor = color)    #get different axes labels together    lns = ln1+ln2     labs = [l.get_label() for l in lns]    ax1.legend(lns,labs,bbox_to_anchor = (0,1.02,1,0.102),loc = 3,ncol = 3,borderaxespad = 0)    #x-axis label rotated to 45 degrees to avoid overlapping    ax1.tick_params(axis = 'x', labelrotation = 45)    # #show the graph    # canvas = FigureCanvasTkAgg(fig_s1,frame)    # canvas.draw()    # canvas.get_tk_widget().pack(side = tk.TOP, fill = tk.BOTH, expand = True)     # #add navigation bar    # toolbar = NavigationToolbar2Tk(canvas,frame)    # toolbar.update()    # canvas._tkcanvas.pack(side = tk.TOP,fill = tk.BOTH, expand = True)#------------------------------------PAGES-----------------------------------#class main(tk.Tk):    def __init__(self, *args, **kwargs):        tk.Tk.__init__(self,*args,**kwargs)        tk.Tk.wm_title(self, "GUI")        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(container)        filemenu = tk.Menu(menubar,tearoff = 0)        filemenu.add_command(label = "Made By", command = lambda: popupmsg("Made By","Not supported yet"))        filemenu.add_separator()        filemenu.add_command(label = "Exit", command = quit)        #add filemenu TO THE menubar        menubar.add_cascade(label = "File", menu= filemenu)        #sensor menu        snsrmenu = tk.Menu(menubar,tearoff = 0)        snsrmenu.add_command(label = "Sensor 1", command = lambda: self.show_frame(GraphS1))        snsrmenu.add_command(label = "Sensor 2", command = lambda: self.show_frame(GraphS2))        snsrmenu.add_command(label = "Sensor 3", command = lambda: self.show_frame(GraphS3))        snsrmenu.add_separator()        snsrmenu.add_command(label = "Exit", command = quit)        #add filemenu TO THE menubar        menubar.add_cascade(label = "Sensors", menu= snsrmenu)        #start stop menubar for the graphs        startstopmenu = tk.Menu(menubar,tearoff=0)        startstopmenu.add_command(label = "Start reading", command = lambda: popupmsg("!","Not supported yet"))        startstopmenu.add_command(label = "Stop reading", command = lambda: popupmsg("!","Not supported yet"))        #add filemenu TO THE menubar        menubar.add_cascade(label = "Start/Stop Graph", menu= startstopmenu)        tk.Tk.config(self,menu=menubar)        self.frames = {}        for f in (StartPage,GraphS1,GraphS2,GraphS3):            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 = tk.Label(self,text = "StartPage", font = LARGE_FONT)        label.pack(pady = 10, padx = 10)        b1 = ttk.Button(self,text = "Open page to run sensor 1",        command = lambda: control.show_frame(GraphS1))        b1.pack()        b2 = ttk.Button(self,text = "Exit",        command = quit)        b2.pack()class GraphS1(tk.Frame):    def __init__(self,parent,control):        tk.Frame.__init__(self,parent)        label = tk.Label(self,text = "Real-time Graph ",font = LARGE_FONT)        label.pack()        b1 = ttk.Button(self,text = "Go back to StartPage",        command = lambda: control.show_frame(StartPage))        b1.pack()        b2 = ttk.Button(self,text = "Pause",        command = lambda: anim.event_source.stop())        b2.pack()        b3 = ttk.Button(self,text = "Play",        command = lambda: anim.event_source.start())        b3.pack()        b4 = ttk.Button(self,text = "Exit",        command = quit)        b4.pack()class GraphS2(tk.Frame):    def __init__(self,parent,control):        tk.Frame.__init__(self,parent)        label = tk.Label(self,text = "Real-time Graph S2",font = LARGE_FONT)        label.pack()        b1 = ttk.Button(self,text = "Go back to StartPage",        command = lambda: control.show_frame(StartPage))        b1.pack()        b4 = ttk.Button(self,text = "Exit",        command = quit)        b4.pack()class GraphS3(tk.Frame):    def __init__(self,parent,control):        tk.Frame.__init__(self,parent)        label = tk.Label(self,text = "Real-time Graph S3",font = LARGE_FONT)        label.pack()        b1 = ttk.Button(self,text = "Go back to StartPage",        command = lambda: control.show_frame(StartPage))        b1.pack()        b4 = ttk.Button(self,text = "Exit",        command = quit)        b4.pack()#--------------------CALL MAIN CLASS-------------------------------------------------------##call main classgui = main()   # gui.geometry("1280x720")gui.state('zoomed') #maximise window#call animation classanim = animation.FuncAnimation(fig_s1,animate_graph,                               fargs = (x_s1,y1_s1,y2_s1,ax1_s1,ax2_s1),interval = 1000)#run in loopgui.mainloop()

I have only programmed the sensor 1 page, but not the other two. I am assuming it will be the same approach for the other two.

Image for Start Page

Image for Sensor 1 Page

Thanks in advance.

EDIT1: Made huge changes to the project to something I can work with. Won't need this anymore. Just leaving this here incase anyone has a solution to it. might help someone else


Viewing all articles
Browse latest Browse all 23131

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>