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

如何在PyQt6的Matplotlib画布中添加新Figure对象而不清除原有绘图

问题:在PyQt6的Matplotlib画布中叠加绘制独立Figure对象

我正在用PyQt6构建带Matplotlib图形可视化的GUI,待展示的图形由函数生成并返回独立的matplotlib.figure.Figure对象(该对象不由pyplot管理,且不愿修改此生成方式)。现在需要实现:在已绘制过图形的同一个Matplotlib画布中,叠加绘制新的Figure对象,且不清除原有绘图。

现有MplWidget的最小可运行示例中,update_figure方法已实现替换画布内容(绘制首个Figure),但add_figure方法尚未实现叠加功能:

# ------------------------------------------------------
# -------------------- mplwidget.py --------------------
# ------------------------------------------------------
from PyQt6.QtWidgets import*
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
from matplotlib.figure import Figure
from PyQt6.QtGui import QFont, QFontInfo
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Qt5Agg')
    
class MplWidget(QWidget):
    
    def __init__(self, parent = None):
        super(QWidget, self).__init__()
        self.canvas = FigureCanvasQTAgg(Figure()) 
        vertical_layout = QVBoxLayout()
        vertical_layout.addWidget(self.canvas)
        self.canvas.axes = self.canvas.figure.add_subplot(111)
        self.canvas.draw()
        
        # 获取系统默认字体并应用到画布
        self.resetFontStyle()
        self.setLayout(vertical_layout)
    
    def update_figure(self, new_figure):
        # new_figure 是 matplotlib Figure 对象
        # 清除现有内容
        self.canvas.figure.clf()
        self.canvas.axes = self.canvas.figure.add_subplot(111)
        # 复制新Figure的内容到当前画布
        # 修正原逻辑:避免直接替换figure对象导致绑定异常
        for ax in new_figure.get_axes():
            for line in ax.get_lines():
                self.canvas.axes.plot(line.get_xdata(), line.get_ydata(), 
                                     label=line.get_label(), **line.get_properties())
            # 同步轴标签、标题
            self.canvas.axes.set_xlabel(ax.get_xlabel())
            self.canvas.axes.set_ylabel(ax.get_ylabel())
            self.canvas.axes.set_title(ax.get_title())
        self.canvas.draw()

    def add_figure(self, new_figure):
        # new_figure 是 matplotlib Figure 对象
        # 遍历新Figure的所有子图
        for new_ax in new_figure.get_axes():
            # 复制子图中的线条类元素(plot曲线等)
            for line in new_ax.get_lines():
                self.canvas.axes.plot(line.get_xdata(), line.get_ydata(), 
                                     label=line.get_label(), **line.get_properties())
            # 复制散点图元素
            for collection in new_ax.collections:
                if isinstance(collection, matplotlib.collections.PathCollection):
                    self.canvas.axes.scatter(collection.get_offsets()[:,0], 
                                            collection.get_offsets()[:,1],
                                            s=collection.get_sizes(),
                                            c=collection.get_facecolors(),
                                            label=collection.get_label())
            # 可选:同步轴标签(按需开启)
            # self.canvas.axes.set_xlabel(new_ax.get_xlabel())
            # self.canvas.axes.set_ylabel(new_ax.get_ylabel())
        # 添加图例(如果元素带标签)
        self.canvas.axes.legend()
        # 重绘画布
        self.canvas.draw()

    def resetFontStyle(self):
        font = QFont()
        font_info = QFontInfo(font)
        matplotlib.rcParams['font.family'] = font_info.family()
        matplotlib.rcParams['font.size'] = font.pointSize()

关键实现说明

  1. 避免直接替换Figure对象:原update_figure中直接替换self.canvas.figure = new_figure会导致画布与原Figure的绑定关系失效,改为复制子图元素到当前画布的轴中。
  2. 叠加绘制核心逻辑:
    • 遍历新Figure的所有子图(new_figure.get_axes())
    • 提取子图中的线条(get_lines())、散点(collections)等可视化元素,完整复制样式(颜色、标签、大小等)到当前画布的轴上
  3. 可选扩展:如果需要支持直方图、柱状图等其他类型的绘图,需对应提取patches等元素并复制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:05:35