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

如何实现选择新文件时自动更新Canvas中的Matplotlib图表?

JSON数据可视化GUI图表更新问题

问题描述

我正在开发一个用于可视化JSON数据的GUI,目前遇到的问题是无法让Canvas中的图表更新,仅在点击窗口最大化/最小化按钮时才会更新。请问是否有办法在选择新文件时更新图表?

界面状态说明

  • 图表未及时更新状态:选择新文件后图表区域无内容,仅在窗口缩放(最大化/最小化)后才显示对应数据的图表
  • GUI界面:包含用于选择文件的列表框和图表展示Canvas区域

相关代码

##### Canvas ####
figure = plt.figure()
canvas = FigureCanvasTkAgg(figure, master=inspect_data)
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)


###### file gets selected #####


def items_selected(d):
    plt.clf()
    selected_indices = vores_listebox.curselection()
    selected_json = ",".join([vores_listebox.get(i) for i in selected_indices])
    full_file_path = path_us + selected_json
    open_json = js.load(open(full_file_path, "r"))
    time = [open_json['XML_Data']
            ['Wsk3Vectors']['X_Axis']['Values']['float']]
    rpm = [open_json['XML_Data']['Wsk3Vectors']
           ['Y_AxesList']['AxisData'][0]['Values']['float']]
    torque = [open_json['XML_Data']['Wsk3Vectors']
              ['Y_AxesList']['AxisData'][1]['Values']['float']]
    current = [open_json['XML_Data']['Wsk3Vectors']
               ['Y_AxesList']['AxisData'][2]['Values']['float']]
    angle = [open_json['XML_Data']['Wsk3Vectors']
             ['Y_AxesList']['AxisData'][3]['Values']['float']]
    depth = [open_json['XML_Data']['Wsk3Vectors']
             ['Y_AxesList']['AxisData'][4]['Values']['float']]


###### Using Matlib.pyplot to plot 5 graphs ######
    plt.rcParams["figure.figsize"] = (7, 10)

    plt.subplot(5, 1, 1)
    plt.scatter(time, rpm, c="b", linewidths=2,
                marker=",", edgecolor="b", s=1, alpha=0.5)
    plt.title(selected_json)
    plt.gca().axes.xaxis.set_ticklabels([])
    plt.ylabel("RPM")
    plt.grid()

    plt.subplot(5, 1, 2)
    plt.scatter(time, torque, c="g", linewidths=1,
                marker=",", edgecolor="g", s=1, alpha=0.3)
    plt.gca().axes.xaxis.set_ticklabels([])
    plt.ylabel("Torque [Nm]")
    plt.grid()

    plt.subplot(5, 1, 3)
    plt.scatter(time, current, c="r", linewidths=2,
                marker=",", edgecolor="r", s=1, alpha=0.5)
    plt.gca().axes.xaxis.set_ticklabels([])
    plt.ylabel("Current [Amps]")
    plt.grid()

    plt.subplot(5, 1, 4)
    plt.scatter(time, angle, c="m", linewidths=2,
                marker=",", edgecolor="m", s=1, alpha=0.5)
    plt.gca().axes.xaxis.set_ticklabels([])
    plt.ylabel("Angle [RAD]")
    plt.grid()

    plt.subplot(5, 1, 5)
    plt.scatter(time, depth, c="c", linewidths=2,
                marker=",", edgecolor="c", s=1, alpha=0.5)
    plt.xlabel("Time [ms]")
    plt.ylabel("Depth [mm]")
    plt.grid()


vores_listebox.bind('<<ListboxSelect>>', items_selected)

我已尝试使用root.update()、Canvas.update()等命令,但均无效,恳请提供解决帮助!


解决方案

核心修复:触发Canvas重绘

问题根源是绘制完图表后未主动通知FigureCanvasTkAgg更新界面。在items_selected函数的最后,添加以下两行代码即可触发实时更新:

canvas.draw()
canvas.flush_events()

修改后的完整函数结尾如下:

plt.subplot(5, 1, 5)
    plt.scatter(time, depth, c="c", linewidths=2,
                marker=",", edgecolor="c", s=1, alpha=0.5)
    plt.xlabel("Time [ms]")
    plt.ylabel("Depth [mm]")
    plt.grid()

    # 新增:触发图表更新
    canvas.draw()
    canvas.flush_events()
  • canvas.draw():强制重新渲染图表内容
  • canvas.flush_events():处理所有待处理的GUI事件,确保绘制结果立即显示

优化建议:改用面向对象绘图方式

避免混用pyplot全局状态和FigureCanvasTkAgg,改用面向对象方式操作figure对象,减少状态冲突,代码更易维护:

# 初始化Canvas时设置图尺寸
figure = plt.figure(figsize=(7, 10))
canvas = FigureCanvasTkAgg(figure, master=inspect_data)
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)

def items_selected(d):
    figure.clear()  # 用figure.clear()替代plt.clf()
    # ... 读取JSON数据部分保持不变 ...
    
    # 创建5行1列的子图数组
    axs = figure.subplots(5, 1)
    
    # 绘制第一个子图
    axs[0].scatter(time, rpm, c="b", linewidths=2, marker=",", edgecolor="b", s=1, alpha=0.5)
    axs[0].set_title(selected_json)
    axs[0].set_ylabel("RPM")
    axs[0].tick_params(axis='x', labelbottom=False)  # 隐藏x轴标签
    axs[0].grid(True)
    
    # 绘制第二个子图
    axs[1].scatter(time, torque, c="g", linewidths=1, marker=",", edgecolor="g", s=1, alpha=0.3)
    axs[1].set_ylabel("Torque [Nm]")
    axs[1].tick_params(axis='x', labelbottom=False)
    axs[1].grid(True)
    
    # 绘制第三个子图
    axs[2].scatter(time, current, c="r", linewidths=2, marker=",", edgecolor="r", s=1, alpha=0.5)
    axs[2].set_ylabel("Current [Amps]")
    axs[2].tick_params(axis='x', labelbottom=False)
    axs[2].grid(True)
    
    # 绘制第四个子图
    axs[3].scatter(time, angle, c="m", linewidths=2, marker=",", edgecolor="m", s=1, alpha=0.5)
    axs[3].set_ylabel("Angle [RAD]")
    axs[3].tick_params(axis='x', labelbottom=False)
    axs[3].grid(True)
    
    # 绘制第五个子图
    axs[4].scatter(time, depth, c="c", linewidths=2, marker=",", edgecolor="c", s=1, alpha=0.5)
    axs[4].set_xlabel("Time [ms]")
    axs[4].set_ylabel("Depth [mm]")
    axs[4].grid(True)
    
    # 触发更新
    canvas.draw()
    canvas.flush_events()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 17:05:28