0

Load Graphs quickly without a lag or flicker when user switch from one screen to another or even when close the application. Currently, I am using a small data to recreate this problem but in actual application I have 1000 data points to display on graph.

Steps to recreate the issue.

  1. Click on Maximize Button to see the flicker or lag.
  2. Close the application , you will see graphs rearranging on screen before close.
from tkinter import *
from pandas import DataFrame
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import threading as th

class AppLayout(Tk):
    def __init__(self):
        Tk.__init__(self)

        self.masterPane = PanedWindow(self )
        self.leftPane   = Frame(self.masterPane,relief = 'raised',bg='black',width =100)
        self.masterPane.add(self.leftPane)
        
        self.rightPane   = Frame(self.masterPane,bg ='#0C0026')
        self.rightPane.columnconfigure(2, weight=1)
        self.masterPane.add(self.rightPane)
        
        self.masterPane.pack(fill = 'both',expand = True)
        self.dashBoard()
        
    def dashBoard(self):
      
        self.Dashboard_Frame = Frame(self.rightPane,bg ='#0C0026')
        self.Dashboard_Frame.grid(row=0,column =0,sticky ='nsew')
        
        def Display_Chart():
            
            def Draw_Graph(fig_dim,fig_pady,fig_padx,fig_row,fig_column,fig_sticky):
                  
                data1 = {'Country': ['US','CA','GER','UK','FR','IN'],
                         'GDP_Per_Capita': [45000,42000,52000,49000,47000,85000]
                         }
                df1 = DataFrame(data1,columns=['Country','GDP_Per_Capita'])
            
                figure1 = plt.Figure(figsize= fig_dim, dpi=100)
                ax1 = figure1.add_subplot(111)
                bar1 = FigureCanvasTkAgg(figure1, self.Dashboard_Frame)
                bar1.get_tk_widget().grid(row=fig_row,column =fig_column,sticky =fig_sticky,pady=fig_pady,padx=fig_padx)
                                   
                df1 = df1[['Country','GDP_Per_Capita']].groupby('Country').sum()
                df1.plot(kind='line', legend=True, ax=ax1,color ='w')
                ax1.set_title('Country Vs. GDP Per Capita',color ='w')
                
                ax1.yaxis.label.set_color('w')
                ax1.xaxis.label.set_color('w')
                ax1.spines['bottom'].set_color('w')
                ax1.spines['top'].set_color('w') 
                ax1.spines['right'].set_color('w')
                ax1.spines['left'].set_color('w')
                figure1.patch.set_facecolor('w')
                
                ax1.tick_params(colors='w', which='both')
            
                ax1.set_facecolor('#0a043c')
                figure1.set_facecolor('#000839')
                
                self.Dashboard_Frame.rowconfigure(1, weight=1)
                self.Dashboard_Frame.columnconfigure(0, weight=1)
        
            th.Thread(target = Draw_Graph((6,3),(40,10),20,1,0,'nswe')).start()
            th.Thread(target = Draw_Graph((6,3),(0,20),20,2,0,'nswe')).start()
            
            th.Thread(target = Draw_Graph((4,2),(40,10),0,1,1,'nswe')).start()
            th.Thread(target = Draw_Graph((4,2),(0,20),0,2,1,'nswe')).start()
            
            self.rightPane.columnconfigure(0, weight=1)
            self.rightPane.rowconfigure(0, weight=1)
            self.Dashboard_Frame.rowconfigure(1, weight=1)         
            self.Dashboard_Frame.rowconfigure(2, weight=1)       
            self.Dashboard_Frame.columnconfigure(0, weight=1)
            self.Dashboard_Frame.columnconfigure(1, weight=1)
            self.Dashboard_Frame.columnconfigure(3, weight=1)

        
        th.Thread(target=Display_Chart()).start()


app = AppLayout()
app.mainloop()
Anni
  • 77
  • 7
  • You shouldn't use `tkinter` from multiple threads. Sometimes tkinter can crash without even giving you an error message – TheLizzard May 09 '21 at 19:46
  • I tried in single thread since it didn't work so I tried to add Graphs in separate thread but unfortunately even that didn't show much improvement. – Anni May 09 '21 at 19:50
  • Why don't you hide the window using `.withdraw()` then show a progress bar while the graphs are being shown? After that you can use `.deiconify()` to show the window again – TheLizzard May 09 '21 at 19:53
  • Thanks for your reply. Certainly, I can do that but that will be last resort if optimization is not possible at all. Right Now my focus is how to reduce the graph load time if there is any way to do it. – Anni May 09 '21 at 21:51
  • I really don't know how `pandas` or `matplotlib` word but I have a suspicion that `df1 = DataFrame(data1,columns=['Country','GDP_Per_Capita'])` and `df1 = df1[['Country','GDP_Per_Capita']].groupby('Country').sum()` are taking quite a bit of time. Is there a way to run that on the app start up? – TheLizzard May 09 '21 at 21:56
  • I can't use it in app startup because data is not static. I used df1 to recreate the problem because you won't have access to the actual data source. Also, if I will load the data in app startup and user doesn't press the graph button for 10 mins... he will see 10 mins old data. that was loaded during app startup and If he presses refresh then again we will see the same problem of graph load time again. So, in any case I have to reduce the graph load time. – Anni May 10 '21 at 19:10
  • Also I just want to point out that using `th.Thread(target=(...).start()` doesn't start the function in a new thread. It runs the function before you even create a new thread then assigns `target` to `None`. It is very similar to [this](https://stackoverflow.com/a/5771787/11106801) – TheLizzard May 10 '21 at 19:46

0 Answers0