Home > Enterprise >  How to resolve misplaced subplots in tkinter canvas?
How to resolve misplaced subplots in tkinter canvas?

Time:11-04

I am having this problem where I create 4 subplots on a canvas on parent frame and first turn creating figure is okay (see pic attached)

And for 2nd time, I clear the canvas using a function, then again plot, but I see a misplaced graph and multiple copies of matplotlib toolbar (see attached)

Reproducible example:

import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import tkinter as tk

def fnc1to2():
    print("1 to 2")
    frame1.pack_forget()
    frame2.pack(fill="both", expand=True)

def fnc2to3():
    print("2 to 3")
    frame2.pack_forget()
    frame3.pack(fill="both", expand=True)

def fnc2to1():
    print("2 to 1")
    frame2.pack_forget()
    frame1.pack(fill="both", expand=True)

def fnc3to2():
    print("3 to 2")
    frame3.pack_forget()
    frame2.pack(fill="both", expand=True)

def fileget():    
      
        global f
        f = Figure(figsize=(3,3), dpi=100,constrained_layout=True)
        f.set_constrained_layout_pads(w_pad=9 / 72, h_pad=4 / 72, hspace=0.2,
                                wspace=0.15)
        #a = f.add_subplot(221,xlim=(t[0],t[-1]),ylim=(-3000,3000))
        #fig1, ax = matplotlib.pyplot.subplots()
        a = f.add_subplot(221)
        a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
        a.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)') 
        #a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
        a1 = f.add_subplot(222)
        a1.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])    
        a1.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
        a2 = f.add_subplot(223)
        a2.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
        a2.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
        a3 = f.add_subplot(224)
        a3.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
        a3.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')
        global canvas1
        canvas1 = FigureCanvasTkAgg(f, frame3)
        canvas1.draw()
        canvas1.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
        toolbar = NavigationToolbar2Tk(canvas1, frame3)
        toolbar.update()
        canvas1._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)  
        
def clearplot():
    f.clear() 
    #f.clf()
    for item in canvas1.get_tk_widget().find_all():
        canvas1.get_tk_widget().delete(item)
    canvas1.draw()
    
root = tk.Tk()
root.geometry("1280x1080")
frame1 = tk.Frame(root, bg = "azure3")
frame2 = tk.Frame(root, bg = "seashell2")
frame3 = tk.Frame(root, bg = "honeydew2")


#lab1f1 = tk.Label(frame1, text = "Label 1 in Frame 1")
lab1f2 = tk.Label(frame2, text = "Label 1 in Frame 2")
lab1f3 = tk.Label(frame3, text = "Manual log analysis", font=12)

btn1to2 = tk.Button(frame1, text = "Start", command = fnc1to2)

btn2to1 = tk.Button(frame2, text = "Back to home", command = fnc2to1)

btn2to3 = tk.Button(frame2, text = "Manual log", command = fnc2to3)

btn3to2 = tk.Button(frame3, text = "Select log type", command = fnc3to2)

btn3to3 = tk.Button(frame3, text = "Connect", command = fileget)

btn3reset = tk.Button(frame3, text = "Clear", command = clearplot)

#frame 1
btn1to2.pack()

#frame 2
f2label = tk.Label(frame2, text="Select log type to visualize!!!", font=12)
f2label.pack(pady=10,padx=10)
lab1f2.pack()
btn2to3.pack()
btn2to1.pack()

#frame 3
lab1f3.pack()
btn3to3.pack()
btn3to2.pack()
btn3reset.pack()

frame1.pack(fill="both", expand=True)
root.mainloop()

CodePudding user response:

It is because you create new set of figure and toolbar every time fileget() is executed. You need to remove previous set of figure and toolbar by calling clearplot() at the beginning of fileget().

Below are the modified fileget() and clearplot():

def fileget():
    global f, canvas1, toolbar

    clearplot() # destroy previous figure and toolbar

    f = Figure(figsize=(3,3), dpi=100, constrained_layout=True)
    f.set_constrained_layout_pads(w_pad=9/72, h_pad=4/72, hspace=0.2, wspace=0.15)

    a = f.add_subplot(221)
    a.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
    a.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')

    a1 = f.add_subplot(222)
    a1.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
    a1.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')

    a2 = f.add_subplot(223)
    a2.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
    a2.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')

    a3 = f.add_subplot(224)
    a3.plot([1,2,3,4,5,6,7,8],[5,6,1,3,8,9,3,5])
    a3.set(title = "Switch ON Energy losses - E_ON", xlabel = 'Current (A)', ylabel = 'Energy (mJ)')

    canvas1 = FigureCanvasTkAgg(f, frame3)
    canvas1.draw()
    canvas1.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)

    toolbar = NavigationToolbar2Tk(canvas1, frame3)
    toolbar.update()

def clearplot():
    global canvas1, toolbar
    try:
        canvas1.get_tk_widget().destroy()
        toolbar.destroy()
    except:
        # canvas1 and toolbar do not exist
        pass
  • Related