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

如何在Tkinter窗口中更新Matplotlib图表而非新建窗口

问题:Tkinter中切换Matplotlib图表出现空白的问题

我希望制作一个可显示Matplotlib图表的Tkinter窗口,无需创建新窗口切换图表。目前我可通过销毁窗口切换,但该方式十分不便。

我的代码如下:

import tkinter as tk
from tkinter import *
from matplotlib.pyplot import *
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure

#global variables
global stopper
data = (([1,2,3,4,5], [1,2,3,4,5]), ([1,2,3,4,5],[5,4,3,2,1]))
window = tk.Tk()
window.geometry("500x500")

def Descision(event):
    print("go to next dataset")
    stopper.set(1)

for i in data:
    print(i)

    frame = Frame(window, width = 750, height = 750)    #make a new frame
    frame.pack()
    frame.place(anchor='center', relx=0.5, rely=0.5)
    fig = Figure(figsize = (5, 5), dpi = 100)

    stopper = IntVar(window, 0)     

    plot1 = fig.add_subplot(111)

    plot1.plot(i[0], i[1])

    canvas = FigureCanvasTkAgg(fig, master = window)

    canvas.draw()

    canvas.get_tk_widget().pack()

    window.bind("<Key>", lambda event : Descision(event))

    window.wait_variable(stopper)   #wait until user presses a key
    frame.destroy()
    #canvas.clear()     #"AttributeError: 'FigureCanvasTkAgg' object has no attribute 'clear'"

我想要从data[0]生成的图表切换到data[1]生成的图表,但销毁框架后显示的图表为空白,请问哪里理解有误?


问题原因

  1. 重复创建组件未清理:每次循环都新建Figure和Canvas,旧的Canvas组件没有被销毁,会留在窗口中遮挡新图表,导致显示异常。
  2. Frame逻辑冗余:你创建了Frame但并未将Canvas放入其中,销毁Frame对Canvas没有影响,旧组件残留引发显示混乱。
  3. 重复绑定事件:每次循环都执行window.bind("<Key>", ...),导致事件被多次绑定,触发时可能出现不可预期的行为。

修复方案

复用同一个Figure和Canvas,仅更新图表数据即可,无需反复创建新组件。修改后的代码如下:

import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

data = (([1,2,3,4,5], [1,2,3,4,5]), ([1,2,3,4,5],[5,4,3,2,1]))
window = tk.Tk()
window.geometry("500x500")

# 初始化一次Figure、Canvas和Axes
fig = Figure(figsize=(5, 5), dpi=100)
plot1 = fig.add_subplot(111)
canvas = FigureCanvasTkAgg(fig, master=window)
canvas.get_tk_widget().pack()

current_index = 0

def update_plot(index):
    # 清除旧图表内容
    plot1.clear()
    # 绘制新数据
    x, y = data[index]
    plot1.plot(x, y)
    # 刷新Canvas
    canvas.draw()

def switch_dataset(event):
    global current_index
    # 切换索引,循环显示
    current_index = (current_index + 1) % len(data)
    update_plot(current_index)
    print(f"切换到数据集{current_index+1}")

# 只绑定一次按键事件
window.bind("<Key>", switch_dataset)

# 初始显示第一个数据集
update_plot(current_index)

window.mainloop()

修改说明

  • 将Figure、Canvas和Axes(plot1)的初始化移到循环外,只创建一次
  • 新增update_plot函数,负责清除旧图表、绘制新数据并刷新Canvas
  • 用current_index跟踪当前显示的数据集,按键时切换索引并更新图表
  • 仅绑定一次按键事件,避免重复绑定导致的异常

内容的提问来源于stack exchange,提问作者jabo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:15:02