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

Matplotlib双动态图表问题:左侧空白、Y轴刻度失效及迭代器异常

进程监控工具双图表问题修复方案

问题1:动态滚动图表左侧空白

根因

依赖FuncAnimation传入的i作为迭代计数器,但该参数在动画初始化阶段会重复传入0,导致前两次循环X轴范围设置错误,出现左侧空白。

修复方案

在类内部维护独立计数器,替代FuncAnimation传入的i:

  • 在__init__方法中添加self.counter = 0初始化计数器
  • 在animate方法中使用self.counter替代原i,每次循环完成后执行自增操作

问题2:Y轴刻度设置失效

根因

  1. locator_params(axis="y", nbins=8)仅能减少刻度数量,无法强制增加刻度;
  2. 每次调用graph.clear()后轴配置会被重置,原样式设置逻辑存在覆盖问题,导致仅第二个图表的刻度配置生效。

修复方案

改用MaxNLocator强制指定刻度数量,确保每次清除图表后重新应用配置:

  • 导入from matplotlib.ticker import MaxNLocator
  • 在set_graph_style方法中替换locator_params为graph.yaxis.set_major_locator(MaxNLocator(nbins=8, integer=True))

完整修复代码

import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib.ticker import MaxNLocator
import psutil


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("Graph Test")
        self.geometry("800x300")

        self.figure = Figure(figsize=(8, 3), dpi=100)

        self.cpu_graph = self.figure.add_subplot(121)
        self.set_graph_style(self.cpu_graph)

        self.memory_graph = self.figure.add_subplot(122)
        self.set_graph_style(self.memory_graph)

        canvas = FigureCanvasTkAgg(self.figure, self)
        canvas.get_tk_widget().grid(row=0, column=0)

        self.frame_length = 10

        self.x_list = list(range(self.frame_length))
        self.cpu_y_list = [-1] * self.frame_length
        self.memory_y_list = [-1] * self.frame_length

        # 维护独立计数器,替代FuncAnimation传入的i
        self.counter = 0
        self.anim = animation.FuncAnimation(self.figure, self.animate, interval=1000)

    def animate(self, _):
        # 使用自定义计数器计算X轴范围
        lower_limit = self.counter
        upper_limit = self.counter + self.frame_length

        self.x_list.append(self.counter + self.frame_length)
        self.cpu_y_list.append(psutil.cpu_percent())
        self.memory_y_list.append(psutil.virtual_memory().percent)

        if len(self.cpu_y_list) > self.frame_length:
            self.x_list.pop(0)
            self.cpu_y_list.pop(0)
            self.memory_y_list.pop(0)

        self.cpu_graph.clear()
        self.cpu_graph.plot(self.x_list, self.cpu_y_list, "#117dbb")
        self.cpu_graph.set_title("CPU")
        self.cpu_graph.set_xlim(lower_limit, upper_limit)
        self.cpu_graph.fill_between(self.x_list, self.cpu_y_list, color="#f1f6fa")
        self.set_graph_style(self.cpu_graph)

        self.memory_graph.clear()
        self.memory_graph.plot(self.x_list, self.memory_y_list, "#117dbb")
        self.memory_graph.set_title("Memory")
        self.memory_graph.set_xlim(lower_limit, upper_limit)
        self.memory_graph.fill_between(self.x_list, self.memory_y_list, color="#f1f6fa")
        self.set_graph_style(self.memory_graph)

        # 计数器自增
        self.counter += 1

    def set_graph_style(self, graph):
        graph.grid()

        graph.set_yticklabels([])
        graph.set_xticklabels([])

        graph.set_ylim(0, 100)

        # 替换locator_params为MaxNLocator,强制设置8个整数刻度
        graph.yaxis.set_major_locator(MaxNLocator(nbins=8, integer=True))

        graph.spines["bottom"].set_color("#117dbb")
        graph.spines["left"].set_color("#117dbb")

        graph.spines["top"].set_visible(False)
        graph.spines["right"].set_visible(False)

        graph.margins(x=0)
        self.figure.tight_layout()


if __name__ == "__main__":
    app = App()
    app.mainloop()

额外说明

  • 自定义计数器彻底避免了FuncAnimation初始调用的参数异常,确保X轴范围每次循环都正确更新,消除左侧空白;
  • MaxNLocator支持强制指定刻度数量,不受轴范围自动调整的限制,integer=True保证刻度为整数,更符合CPU/内存百分比的显示需求;
  • 每次清除图表后重新调用set_graph_style,确保两个图表的样式配置都能正确生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:39:37