PySimpleGUI画布更新异常:新图表追加而非替换
PySimpleGUI中Matplotlib图表重复生成时叠加显示的解决方法
问题描述
点击“Generate Plot”按钮生成新的Matplotlib图表时,新图表会追加在旧图表下方,而非替换旧图表,现象如下:
问题原因
每次调用draw_figure函数时,都会创建新的FigureCanvasTkAgg对象,并通过pack()将其添加到Canvas容器的顶部,但从未移除旧的画布控件,导致多次点击后控件不断叠加。
解决方案
核心思路是:每次生成新图表前,先销毁上一次的画布控件;同时复用Matplotlib的Figure对象,避免重复创建造成内存浪费。
修改后的完整代码
import PySimpleGUI as sg import matplotlib.pyplot as plt import numpy as np from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg def draw_figure(canvas, figure): figure_canvas_agg = FigureCanvasTkAgg(figure, canvas) figure_canvas_agg.draw() # 加上expand=1让画布自适应容器大小 figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1) return figure_canvas_agg # 提前初始化Matplotlib绘图对象,复用避免重复创建 fig, ax = plt.subplots(figsize=(6, 4)) # 定义GUI布局 layout = [ [sg.Button('Generate Plot')], # 调整Canvas初始大小匹配图表尺寸 [sg.Canvas(size=(600, 400), key='canvas')], [sg.Button('Exit')] ] window = sg.Window('Time Series Plot', layout, finalize=True) fig_agg = None # 保存上一次的画布对象,用于后续销毁 # 事件循环 while True: event, values = window.read() if event == sg.WIN_CLOSED or event == 'Exit': break if event == 'Generate Plot': # 1. 销毁旧的画布控件(如果存在) if fig_agg is not None: fig_agg.get_tk_widget().destroy() # 2. 清空坐标轴,绘制新的随机序列图 ax.clear() x = np.linspace(1, 50) y = np.random.randn(50) ax.plot(x, y, linewidth=2) # 添加图表标签提升可读性 ax.set_title('随机时间序列图') ax.set_xlabel('样本点') ax.set_ylabel('随机值') ax.grid(alpha=0.3) # 3. 绘制新画布到GUI容器 fig_agg = draw_figure(window['canvas'].TKCanvas, fig) # 退出时释放Matplotlib资源和关闭窗口 plt.close(fig) window.close()
关键改动说明
- 复用Matplotlib对象:将
fig, ax = plt.subplots()移到初始化阶段,每次绘图用ax.clear()清空旧内容,避免重复创建Figure造成内存泄漏。 - 销毁旧控件:用
fig_agg变量记录上一次的画布对象,每次生成新图前调用destroy()移除旧控件,彻底解决叠加问题。 - 优化布局适配:给
pack()添加expand=1参数,让画布自适应Canvas容器大小;调整Canvas初始尺寸匹配图表尺寸,显示更美观。 - 增强图表可读性:添加标题、坐标轴标签和网格线,提升图表的易用性。
内容的提问来源于stack exchange,提问作者mhwh
相关产品推荐
相关产品推荐

