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

Matplotlib与Tkinter:如何通过按钮点击动态更新图表?

解决Tkinter切换页面时Matplotlib图表不重新加载的问题

问题

我在学习用Tkinter和Matplotlib制作带图表的应用时遇到问题:点击按钮切换到图表页面(PageThree)时,图表不会重新加载——图表绘制逻辑在程序启动时就执行了,按下按钮后不会再次运行。点击切换按钮后没有任何更新效果。

原因

你的代码中,所有页面(StartPage、PageOne、PageTwo、PageThree)在应用初始化阶段就被创建完成,PageThree的图表绘制逻辑写在__init__方法里,只会在页面实例化时执行一次。切换页面的show_frame方法只是把已存在的Frame前置显示,不会触发新的绘制逻辑。

解决方案

给页面类添加一个on_show方法,在每次切换到该页面时调用这个方法,把图表绘制/更新的逻辑放在这里。同时修改主应用的show_frame方法,确保切换页面时触发这个回调。

修改后的完整代码

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

LARGE_FONT = ("Verdana", 12)

class SeaofBTCapp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "Sea of BTC client")
        
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}

        for F in (StartPage, PageOne, PageTwo, PageThree):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(StartPage)

    def show_frame(self, cont):
        frame = self.frames[cont]
        # 调用页面的on_show方法(如果存在)
        if hasattr(frame, "on_show"):
            frame.on_show()
        frame.tkraise()

class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        label = tk.Label(self, text="Start Page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)
        button = ttk.Button(self, text="Visit Page 1",
                            command=lambda: controller.show_frame(PageOne))
        button.pack()
        button2 = ttk.Button(self, text="Visit Page 2",
                            command=lambda: controller.show_frame(PageTwo))
        button2.pack()
        button3 = ttk.Button(self, text="Graph Page",
                            command=lambda: controller.show_frame(PageThree))
        button3.pack()

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page One!!!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)
        button1 = ttk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(StartPage))
        button1.pack()
        button2 = ttk.Button(self, text="Page Two",
                            command=lambda: controller.show_frame(PageTwo))
        button2.pack()

class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page Two!!!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)
        button1 = ttk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(StartPage))
        button1.pack()
        button2 = ttk.Button(self, text="Page One",
                            command=lambda: controller.show_frame(PageOne))
        button2.pack()

class PageThree(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="Graph Page!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)
        button1 = ttk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(StartPage))
        button1.pack()
        # 初始化图表相关的实例属性,方便后续更新
        self.figure = None
        self.canvas = None

    def on_show(self):
        # 如果已经有图表,先清除旧的画布
        if self.canvas:
            self.canvas.get_tk_widget().pack_forget()
        
        # 重新创建图表(这里可以替换成动态数据)
        self.figure = Figure(figsize=(5,5), dpi=100)
        a = self.figure.add_subplot(111)
        a.plot([1,2,3,4,5,6,7,8],[1,2,3,4,5,6,7,8])
        self.canvas = FigureCanvasTkAgg(self.figure, self)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)

app = SeaofBTCapp()
app.mainloop()

关键修改说明

  1. 主应用show_frame方法:新增了检查并调用页面on_show方法的逻辑,确保每次切换页面时触发该页面的专属更新逻辑。
  2. PageThree类:
    • 将图表绘制逻辑从__init__移到on_show方法,每次切换到该页面都会重新执行绘制。
    • 添加了旧画布清除逻辑,避免多次切换后图表叠加。
    • 可以在on_show中替换成动态数据(比如随机生成新的绘图数据),实现每次切换都展示不同的图表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 01:00:58