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

PyQt+Matplotlib绘图在不同显示器上出现异常行为

问题分析与解决方案

你的代码实现存在错误,并非Matplotlib与PyQt的Bug,问题出在重复创建画布+混用全局pyplot接口的逻辑上,不同显示器的表现差异是因为DPI缩放设置不同,错误在高DPI环境(通常笔记本屏幕)下暴露更明显。

核心错误点

  • 每次点击按钮都创建新的FigureCanvasQTAgg实例,并用replaceWidget替换旧画布,但旧画布未被正确销毁,导致资源泄漏和渲染冲突
  • 使用全局的plt.plot()绘图,而非绑定到当前轴对象self.ax,会干扰Matplotlib的内部状态,重复绘制时出现线条叠加/变粗的问题
  • 替换画布的操作会打乱Qt的布局管理,在窗口resize时触发布局错乱

修正后的代码

import matplotlib.pyplot as plt
from random import random
from PyQt6 import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg


class Window(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.resize(1126, 568)
        self.centralwidget = QtWidgets.QWidget()
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.pushButtonConnect = QtWidgets.QPushButton("Connect")
        self.gridLayout.addWidget(self.pushButtonConnect, 0, 0, 1, 1)
        self.setCentralWidget(self.centralwidget)
        
        # 初始化画布和轴,复用同一实例
        self.fig, self.ax = plt.subplots()
        self.canvas = FigureCanvasQTAgg(self.fig)
        self.gridLayout.addWidget(self.canvas, 0, 1, 1, 1)
        
        self.pushButtonConnect.clicked.connect(self.runGraph)
        self.ax.set_xlim([0, 1])
        self.ax.set_ylim([0, 1])
        # 初始绘制空白画布
        self.canvas.draw()

    def runGraph(self):
        # 可选:如果需要每次点击清空旧数据,取消下面注释
        # self.ax.clear()
        # self.ax.set_xlim([0, 1])
        # self.ax.set_ylim([0, 1])
        
        # 使用当前轴对象绘图,而非全局plt
        self.ax.plot([random(), random()], [random(), random()])
        # 刷新画布即可,无需替换
        self.canvas.draw_idle()


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    win = Window()
    win.show()
    app.exec()

关键修改说明

  1. 复用画布实例:全程使用同一个self.canvas,不再创建新实例替换,避免布局和资源问题
  2. 绑定轴对象绘图:用self.ax.plot()替代plt.plot(),确保绘图操作仅作用于当前窗口的图表,不干扰全局状态
  3. 刷新画布而非替换:调用self.canvas.draw_idle()高效刷新图表显示,这是Matplotlib在Qt中更新绘图的标准方式
  4. 可选清空旧数据:如果需要每次点击显示全新数据而非叠加,取消self.ax.clear()及重置坐标轴范围的注释即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:33:32