You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Tkinter canvas中Matplotlib子图错位、工具栏重复显示问题

问题描述

我在父框架的canvas上创建4个子图,首次生成图形时显示正常:
见附图
通过自定义函数清空画布后重新绘图,出现了图形错位,同时存在多份Matplotlib toolbar副本的问题:
见附图

问题原因
  1. 每次触发绘图操作时都会重新创建新的FigureCanvasTkAgg画布和NavigationToolbar2Tk工具栏实例,旧实例没有被销毁,直接堆积在页面框架中,引发布局错位、多个工具栏重复显示的问题
  2. 原清空逻辑仅删除了画布上的绘制元素,没有处理多余的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 18:54:03