Mert Şölen
Mert Şölen

Reputation: 61

How To Fix Tkinter GUI Freezing During Long Calculation

I have my button and function in GUI as shown below. RUN function calculates X and Y coordinates along with color values and then plots them using matplotlib. Since the calculations and plotting takes time, Tkinter freezes until it's completed. I've seen people using threading but I couldn't really adapt it to my own code. How can I stop Tkinter from freezing?

RUNButton = Button(RUNFrame, text="RUN", width = 10, style='RUN.TButton', command = lambda: RUN(voidORinc.get()))
RUNButton.grid(row=0,column=0,padx=10,ipady=15,pady=5,columnspan=2)

def RUN(inclusion):
    global deformationType
    global NL
    global EL
    global ENL
    global cEntry
    global dEntry
    global dropElementType
    global axstress_xx
    global axstress_xy
    global axstress_yx
    global axstress_yy
    global axstrain_xx
    global axstrain_xy
    global axstrain_yx
    global axstrain_yy
    global axdisp_x
    global axdisp_y
    global analysisType

    (ENL,DOFs,DOCs) = assign_BCs(NL,deformationType.get())
    
    K = assemble_stiffness( ENL ,EL , NL , int(cEntry.get()) , int(dEntry.get()) , inclusion )
    
    Fp = assemble_forces(ENL,NL)
    
    Up = assemble_displacements(ENL,NL)
    
    K_reduced = K[0:DOFs, 0:DOFs] #K_UU
    K_UP = K[0:DOFs, DOFs:DOCs+DOFs]
    K_PU = K_PU= K[DOFs:DOCs+DOFs, 0:DOFs]
    K_PP= K[DOFs:DOCs+DOFs, DOFs:DOCs+DOFs]

    F = Fp - (K_UP @ Up)
    
    Uu = np.linalg.solve( K_reduced, F)
    
    Fu = (K_PU @ Uu)  +  (K_PP @ Up)
    
    ENL = update_nodes(ENL,Uu,Fu,NL)
    
    (stress_xx,stress_xy,stress_yx,stress_yy,strain_xx,strain_xy,strain_yx,strain_yy,disp_x,disp_y,X,Y) = post_process(NL, EL, ENL, int(cEntry.get()), int(dEntry.get()), inclusion)
    
    
    option = analysisType.get()
    
    """
    
    POLYGONAL PLOTS
    
    
    """
            
    axstress_xx.cla()
    axstress_xy.cla()
    axstress_yx.cla()
    axstress_yy.cla()
    axstrain_xx.cla()
    axstrain_xy.cla()
    axstrain_yx.cla()
    axstrain_yy.cla()
    axdisp_x.cla()
    axdisp_y.cla()
    
    
    if option == 'Polygonal':
        stress_xxNormalized = (np.mean(stress_xx, axis=0) - np.mean(stress_xx, axis=0).min()) / (np.mean(stress_xx, axis=0).max() - np.mean(stress_xx, axis=0).min())
        stress_xyNormalized = (np.mean(stress_xy, axis=0) - np.mean(stress_xy, axis=0).min()) / (np.mean(stress_xy, axis=0).max() - np.mean(stress_xy, axis=0).min())
        stress_yxNormalized = (np.mean(stress_yx, axis=0) - np.mean(stress_yx, axis=0).min()) / (np.mean(stress_yx, axis=0).max() - np.mean(stress_yx, axis=0).min())
        stress_yyNormalized = (np.mean(stress_yy, axis=0) - np.mean(stress_yy, axis=0).min()) / (np.mean(stress_yy, axis=0).max() - np.mean(stress_yy, axis=0).min())
        strain_xxNormalized = (np.mean(strain_xx, axis=0) - np.mean(strain_xx, axis=0).min()) / (np.mean(strain_xx, axis=0).max() - np.mean(strain_xx, axis=0).min())
        strain_xyNormalized = (np.mean(strain_xy, axis=0) - np.mean(strain_xy, axis=0).min()) / (np.mean(strain_xy, axis=0).max() - np.mean(strain_xy, axis=0).min())
        strain_yxNormalized = (np.mean(strain_yx, axis=0) - np.mean(strain_yx, axis=0).min()) / (np.mean(strain_yx, axis=0).max() - np.mean(strain_yx, axis=0).min())
        strain_yyNormalized = (np.mean(strain_yy, axis=0) - np.mean(strain_yy, axis=0).min()) / (np.mean(strain_yy, axis=0).max() - np.mean(strain_yy, axis=0).min())
        disp_xNormalized = (np.mean(abs(disp_x), axis=0) - np.mean(abs(disp_x), axis=0).min()) / (np.mean(abs(disp_x), axis=0).max() - np.mean(abs(disp_x), axis=0).min())
        disp_yNormalized = (np.mean(abs(disp_y), axis=0) - np.mean(abs(disp_y), axis=0).min()) / (np.mean(abs(disp_y), axis=0).max() - np.mean(abs(disp_y), axis=0).min())
      
        patches = []
    
        for i in range(len(stress_xxNormalized)):
            verts = np.hstack([np.array([X[:,i]]).T,np.array([Y[:,i]]).T])
            polygon = Polygon(verts)
            patches.append(polygon)
            polygon.set_edgecolor('black')
    
        
        cmap = plt.get_cmap('jet')
        
        colors1 = cmap(stress_xxNormalized)
        colors2 = cmap(stress_xyNormalized)
        colors3 = cmap(stress_yxNormalized)
        colors4 = cmap(stress_yyNormalized)
        colors5 = cmap(strain_xxNormalized)
        colors6 = cmap(strain_xyNormalized)
        colors7 = cmap(strain_yxNormalized)
        colors8 = cmap(strain_yyNormalized)
        colors9 = cmap(disp_xNormalized)
        colors10 = cmap(disp_yNormalized)
        
        
        
        collection1 = PatchCollection(patches)
        collection2 = PatchCollection(patches)
        collection3 = PatchCollection(patches)
        collection4 = PatchCollection(patches)
        collection5 = PatchCollection(patches)
        collection6 = PatchCollection(patches)
        collection7 = PatchCollection(patches)
        collection8 = PatchCollection(patches)
        collection9 = PatchCollection(patches)
        collection10 = PatchCollection(patches)
        
        axstress_xx.add_collection(collection1)
        axstress_xy.add_collection(collection2)
        axstress_yx.add_collection(collection3)
        axstress_yy.add_collection(collection4)
        axstrain_xx.add_collection(collection5)
        axstrain_xy.add_collection(collection6)
        axstrain_yx.add_collection(collection7)
        axstrain_yy.add_collection(collection8)
        axdisp_x.add_collection(collection9)
        axdisp_y.add_collection(collection10)
        
        collection1.set_facecolor(colors1)
        collection2.set_facecolor(colors2)
        collection3.set_facecolor(colors3)
        collection4.set_facecolor(colors4)
        collection5.set_facecolor(colors5)
        collection6.set_facecolor(colors6)
        collection7.set_facecolor(colors7)
        collection8.set_facecolor(colors8)
        collection9.set_facecolor(colors9)
        collection10.set_facecolor(colors10)
        
        collection1.set_edgecolor('black')
        collection2.set_edgecolor('black')
        collection3.set_edgecolor('black')
        collection4.set_edgecolor('black')
        collection5.set_edgecolor('black')
        collection6.set_edgecolor('black')
        collection7.set_edgecolor('black')
        collection8.set_edgecolor('black')
        collection9.set_edgecolor('black')
        collection10.set_edgecolor('black')
        
        axstress_xx.autoscale_view()
        axstress_xy.autoscale_view()
        axstress_yx.autoscale_view()
        axstress_yy.autoscale_view()
        axstrain_xx.autoscale_view()
        axstrain_xy.autoscale_view()
        axstrain_yx.autoscale_view()
        axstrain_yy.autoscale_view()
        axdisp_x.autoscale_view()
        axdisp_y.autoscale_view()
    
    """
    
    TRICONTOURF PLOTS
    
    """

    if option == 'Contour':
        stress_xxNormalized = (stress_xx - stress_xx.min()) / (stress_xx.max() - stress_xx.min())
        stress_xyNormalized = (stress_xy - stress_xy.min()) / (stress_xy.max() - stress_xy.min())
        stress_yxNormalized = (stress_yx - stress_yx.min()) / (stress_yx.max() - stress_yx.min())
        stress_yyNormalized = (stress_yy - stress_yy.min()) / (stress_yy.max() - stress_yy.min())
        strain_xxNormalized = (strain_xx - strain_xx.min()) / (strain_xx.max() - strain_xx.min())
        strain_xyNormalized = (strain_xy - strain_xy.min()) / (strain_xy.max() - strain_xy.min())
        strain_yxNormalized = (strain_yx - strain_yx.min()) / (strain_yx.max() - strain_yx.min())
        strain_yyNormalized = (strain_yy - strain_yy.min()) / (strain_yy.max() - strain_yy.min())
        disp_xNormalized = (disp_x - disp_x.min()) / (disp_x.max() - disp_x.min())
        disp_yNormalized = (disp_y - disp_y.min()) / (disp_y.max() - disp_y.min())
        
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = stress_xxNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axstress_xx.tricontourf(x,y,c ,cmap = cmap,levels=1)
        
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = stress_xyNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axstress_xy.tricontourf(x,y,c, cmap = cmap,levels=1)
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = stress_yxNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axstress_yx.tricontourf(x,y,c, cmap = cmap,levels=1)
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = stress_yyNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axstress_yy.tricontourf(x,y,c, cmap = cmap,levels=1)
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = strain_xxNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axstrain_xx.tricontourf(x,y,c, cmap = cmap,levels=1)
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = strain_xyNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axstrain_xy.tricontourf(x,y,c, cmap = cmap,levels=1)
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = strain_yxNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axstrain_yx.tricontourf(x,y,c, cmap = cmap,levels=1)
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = strain_yyNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axstrain_yy.tricontourf(x,y,c, cmap = cmap,levels=1)
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = disp_xNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axdisp_x.tricontourf(x,y,c, cmap = cmap,levels=1)
        for i in range(np.size(X,1)):
            x = X[:,i]
            y = Y[:,i]
            c = disp_yNormalized[:,i]
            cmap = truncate_colormap(plt.get_cmap('jet'), c.min(), c.max())
            axdisp_y.tricontourf(x,y,c, cmap = cmap,levels=1)
    
    canvasAnalysis.draw()

Edit: This is what I tried so far:

def RUN(inclusion):
    ... function content above

RUNFrame = LabelFrame(processFrame)
RUNFrame.grid(row=1,column=2,padx=10)

RUNButton = Button(RUNFrame, text="RUN", width = 10, style='RUN.TButton', command = threading.Thread(target=RUN, args=(voidORinc.get(), )))
RUNButton.grid(row=0,column=0,padx=10,ipady=15,pady=5,columnspan=2)


I get the error "name RUNFrame is not defined"

Upvotes: 0

Views: 873

Answers (1)

furas
furas

Reputation: 142651

Button should run function which creates thread and start it.

If in RUN you use some values from widgets then you could send them as arguments becaues most GUIs don't like to use widgets in separated threads.

Button(..., command=run_calculations)

def run_calculations():
    
    t = threading.Thread(taget=RUN, args=(voidORinc.get(), cEntry.get()) , int(dEntry.get(), ...))
    t.start()
    

Eventually in RUN you should use periodically root.update() (where root is main window) to force tkinter to get key/mouse events from system, send them to widgets, and redraw widgets. And this way it will not freeze. And this doesn't need thread

 def RUN(inclusion):

     # ... some part of code ...

     root.update()

     # ... some part of code ...

     root.update()

     # ... some part of code ...

     root.update()

Upvotes: 2

Related Questions