1. 文档参考
Matplotlib官方使用文档:
Getting started --- Matplotlib 3.10.9 documentation
详细的用法可参考:
Matplotlib 图表------PyQt5、Python-CSDN博客
2.示例
2.1 单个图表
2.1.1 代码
在网上一搜就搞到了一个小示例:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Qt5Agg') # 必须在 import pyplot 之前执行
import matplotlib.pyplot as plt
class QPlotCanvas(FigureCanvas):
def __init__(self, parent=None):
fig, self.ax = plt.subplots()
super().__init__(fig)
self.plot() # 绘制初始图表
def plot(self):
x = [0, 1, 2, 3, 4, 5]
y = [10, 1, 20, 3, 40, 5]
self.ax.plot(x, y, label='示例数据')
self.ax.set_title('PyQt5 中的 matplotlib 图表')
self.ax.legend()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Matplotlib + PyQt5 示例")
plt.rcParams['font.sans-serif'] = ['SimSun'] # 使用宋体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
self.canvas = QPlotCanvas(self)
self.setCentralWidget(self.canvas)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
2.1.2 代码结构分析
看上面的代码,可以看出起主要作用的是类 FigureCanvasQTAgg *,*单看字面意思也可以了解到这个是封装的Qt版的Figure (画布)。大概看了一眼,这个类也是继承了QWidget,所以就可以将其当做是一个控件。
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
还看了一下backend_qt5agg.py 文件的内容(自行添加了注解),可以看到供Qt使用的各个类:
"""
Render to qt from agg
"""
# 导入Matplotlib的后端模块
from .. import backends
# 【关键】强制Matplotlib使用Qt5绑定,禁用Qt6
backends._QT_FORCE_QT5_BINDING = True
# 从QtAgg基础后端导入核心类(忽略导入检查警告)
from .backend_qtagg import ( # noqa: F401, E402 # pylint: disable=W0611
_BackendQTAgg, # 后端基类
FigureCanvasQTAgg, # 画布组件(核心渲染)
FigureManagerQT, # 窗口管理
NavigationToolbar2QT, # Qt工具栏
FigureCanvasAgg, # AGG渲染引擎
FigureCanvasQT) # Qt画布基类
# 导出为Matplotlib官方后端
@_BackendQTAgg.export
# 定义Qt5Agg后端,完全继承QtAgg的所有功能
class _BackendQT5Agg(_BackendQTAgg):
pass
下方代码看出:自定义类继承了matplotlib的类FigureCanvasQTAgg ,plt.subplots()创建了子图,并将其figure 传给了FigureCanvasQTAgg 进行初始化。
class QPlotCanvas(FigureCanvas):
def __init__(self, parent=None):
fig, self.ax = plt.subplots()
super().__init__(fig)
后续跟直接使用Matplotlib创建图表没什么区别了。
def plot(self):
x = [0, 1, 2, 3, 4, 5]
y = [10, 1, 20, 3, 40, 5]
self.ax.plot(x, y, label='示例数据')
self.ax.set_title('PyQt5 中的 matplotlib 图表')
self.ax.legend()
关键点,就是将matplotlib.pyplot 创建的figure 传给 FigureCanvasQTAgg(Qt版画布)。
2.1.3 效果图

2.2 显示多个图表
前面展示了一块画布上显示单个图表的用法,如何显示多个图表(子图)。我也进行了尝试,根据自己的猜想:只要将matplotlib.pyplot 创建的figure 传给 FigureCanvasQTAgg,后续直接在画布上添加就可以。
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import numpy as np
import matplotlib
matplotlib.use('Qt5Agg') # 必须在 import pyplot 之前执行
import matplotlib.pyplot as plt
class QPlotCanvas(FigureCanvas):
def __init__(self, parent=None):
# fig, self.ax = plt.subplots()
# super().__init__(fig)
# self.plot() # 绘制初始图表
self.fig = plt.figure()
super().__init__(self.fig)
self.subplots()
def subplots(self):
#一、折线图(plot)------最常用
#用途:展示数据随时间/变量的变化趋势
#plt.subplot(行数, 列数, 子图序号),序号从1开始,从左到右、从上到下排列。
self.fig.add_subplot(1,3,1)
#1. 准备数据(模拟股价变化)
x = np.arange(1,11) #X轴 1~10天
y = np.array([12,15,13,18,16,20,19,22,25,23]) #Y轴:股价
#2. 绘制折线图(设置线条颜色,样式,宽度)
plt.plot(x,y,color = 'red',linestyle='-.',linewidth=2,marker='o',label='股价')
#3. 添加细节
plt.title('10天股价变化趋势',fontsize=14) #标题及其字体大小
plt.xlabel('天数',fontsize=12)
plt.ylabel('股价(元)',fontsize=12)
plt.legend()
plt.grid(True,alpha=0.3) #网格,alpha:(0~1)
plt.xticks(x) #X轴刻度:显示1~10的所有整数
#二、柱状图(bar/barh)--对比数据
#用途:对比多个类别数据的差异(如不同产品销量、不同班级分数、不同地区人口)
plt.subplot(1,2,2)
#1. 准备数据(模拟不同产品销量)
products = ['产品A','产品B','产品C','产品D',]
sales = [500,720,380,650]
#2. 绘制柱状图(垂直柱状图:bar; 水平柱状图:barh)
colors = ['#4ECDC4', '#45B7D1', '#3498DB', '#2980B9'] # 蓝色系渐变
# plt.bar(products,sales,color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'], width=0.6)
plt.bar(products,sales,color=colors, width=0.6)
#3. 添加细节(给每个柱子添加数值标签)
for i,v in enumerate(sales):
plt.text(i,v+10,str(v),ha='center',fontsize=10) #数值标签位置、对齐方式
plt.title('不同产品销量对比',fontsize=14)
plt.xlabel('产品名称',fontsize=12)
plt.ylabel('销量(件)',fontsize=12)
plt.grid(True,axis='y',alpha=0.3)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Matplotlib + PyQt5 示例")
plt.rcParams['font.sans-serif'] = ['SimSun'] # 使用
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
self.canvas = QPlotCanvas(self)
self.setCentralWidget(self.canvas)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
效果图:
