如何解决 tkinter canvas 中错位的子图?

How to resolve misplaced subplots in tkinter canvas?

我遇到了这个问题,我在父框架的 canvas 上创建了 4 个子图,并且第一次创建图形没问题 ()

第二次,我使用一个函数清除了 canvas,然后再次绘图,但我看到了一张错位的图表和多个 matplotlib 工具栏副本 ()

可重现的例子:

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()

因为每次执行fileget()都会新建一组图形和工具栏。您需要通过在 fileget().

开头调用 clearplot() 来删除之前的一组图形和工具栏

下面是修改后的fileget()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