如何解决Tkinter canvas中Matplotlib子图错位、工具栏重复显示问题
问题描述
我在父框架的canvas上创建4个子图,首次生成图形时显示正常:
通过自定义函数清空画布后重新绘图,出现了图形错位,同时存在多份Matplotlib toolbar副本的问题:
问题原因
- 每次触发绘图操作时都会重新创建新的
FigureCanvasTkAgg画布和NavigationToolbar2Tk工具栏实例,旧实例没有被销毁,直接堆积在页面框架中,引发布局错位、多个工具栏重复显示的问题 - 原清空逻辑仅删除了画布上的绘制元素,没有处理多余的widget实例,也没有适配后续重绘逻辑
修复方案
核心思路是初始化时仅创建一次画布和工具栏实例,后续绘图、清空操作都复用该实例,修改后的完整代码如下:
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 # 清空已有figure内容 f.clear() 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.draw() def clearplot(): global f f.clear() 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") # 初始化绘图相关组件,仅创建一次 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) canvas1 = FigureCanvasTkAgg(f, frame3) 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) 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()
内容的提问来源于stack exchange,提问作者Mayank Dhami
相关产品推荐
相关产品推荐

