PyQtGraph中的PlotWidget详解
前言
PlotWidget 确实是 PyQtGraph 库的基石,它提供了一个开箱即用、功能强大的绘图区域。为了帮你快速构建起对它的整体认知,下面这个表格汇总了其核心特性和在PyQtGraph类体系中的定位。
| 特性维度 | 说明 |
|---|---|
| 核心定位 | 一个高级的、即用型的图表控件,封装了完整的图表组件(坐标轴、标题、图例等),易于嵌入PyQt/PySide应用程序。 |
| 继承关系 | 继承自 QtWidgets.QGraphicsView,因此可以像标准Qt控件一样使用。 |
| 内部核心 | 内部包含一个 PlotItem对象,真正负责管理图表内容(数据曲线、坐标轴等)。PlotWidget的许多方法直接调用其内部 PlotItem的对应方法。 |
| 主要优势 | 开箱即用 :无需手动搭建复杂场景;性能优异 :尤其适合需要快速绘制大量数据或实时更新的场景。 |
核心架构与协作
PlotWidget的强大在于其内部精密的协作关系,下图直观地展示了其核心构成及数据流转路径:

正如流程图所示,PlotWidget内部包含一个 PlotItem作为图表的"大脑"。PlotItem则管理着 ViewBox(负责显示数据和处理交互)、坐标轴(AxisItem)和标签等组件。通过 PlotWidget的 plot()方法添加数据时,它会创建 PlotDataItem等对象并在 ViewBox中渲染 。
基本使用与样式定制
基本的使用流程非常直接,同时允许进行丰富的样式定制。
-
创建与数据绘制:
pythonimport pyqtgraph as pg from PyQt5.QtWidgets import QApplication import numpy as np import sys app = QApplication(sys.argv) plot_widget = pg.PlotWidget(title="基础示例") # 设置图表标题 # 准备并绘制数据 x = np.linspace(0, 10, 100) y = np.sin(x) plot_widget.plot(x, y, pen='b', name='正弦波') # 绘制一条蓝色曲线,并命名 plot_widget.show() sys.exit(app.exec_()) -
背景与网格:
pythonplot_widget.setBackground('w') # 设置背景为白色 plot_widget.showGrid(x=True, y=True, alpha=0.3) # 显示网格并设置透明度 -
坐标轴与标题:
pythonplot_widget.setLabel('left', '幅度', units='V') # 设置坐标轴标签 plot_widget.setLabel('bottom', '时间', units='s') plot_widget.setTitle("信号波形图", color='b', size='14pt') # 设置图表标题 -
线条与数据点 :通过
pen(线条)、symbol(标记点)、symbolBrush(标记填充色)等参数自定义 。python# 绘制带红色圆形标记的实线 plot_widget.plot(x, y, pen='b', symbol='o', symbolSize=5, symbolBrush='r')
效果如图:

PlotWidget常用属性、函数、信号
下面这个表格汇总了 PlotWidget 最常用的属性、函数和信号。
| 类别 | 名称 | 功能描述 | 常用参数/值 |
|---|---|---|---|
| 常用属性 | background |
设置图表区域的背景颜色。 | 颜色字符串(如 'w'代表白色)、十六进制值(如 '#ffffff')、RGB/A元组或 QColor对象。 |
antialiasing |
控制是否开启抗锯齿,使线条和文本边缘更平滑。 | 布尔值(True或 False),开启可能会轻微影响性能。 |
|
interactive |
设置绘图区域是否允许用户交互(如鼠标缩放、拖拽)。 | 布尔值(True或 False)。 |
|
| 核心函数 | plot() |
在图表上绘制曲线或散点图。 | x, y(数据), pen(线条), symbol(数据点标记), name(图例名称)等。 |
setLabel() |
设置坐标轴的标签(标题)。 | axis(轴,如 'left', 'bottom'), text(标签文本), units(单位,可选)。 |
|
setXRange()/ setYRange() |
设置X轴或Y轴的显示范围。 | min(最小值), max(最大值), padding(边距,通常设为0以精确控制)。 |
|
showGrid() |
显示或隐藏背景网格线。 | x(X轴网格), y(Y轴网格), alpha(网格线透明度)。 |
|
addLegend() |
在图表上添加图例,需要与 plot()函数中的 name参数配合使用。 |
无参数或通过 offset参数设置图例位置。 |
|
clear() |
清除图表上所有的绘图项。 | 无参数。 | |
| 重要信号 | sigXRangeChanged |
当X轴的显示范围发生变化时(例如用户通过鼠标缩放或拖拽)发出此信号。 | |
sigYRangeChanged |
当Y轴的显示范围发生变化时发出此信号。 |
核心功能详解与代码示例
下面我们结合具体代码,进一步了解这些功能如何协同工作。
-
基本图表设置与绘制
下面的代码展示了如何创建一个基本的图表,包括设置背景、标题、坐标轴标签和网格。
pythonimport pyqtgraph as pg from PyQt5.QtWidgets import QApplication import sys import numpy as np app = QApplication(sys.argv) # 创建PlotWidget plot_widget = pg.PlotWidget() # 设置背景为白色 plot_widget.setBackground('w') # 设置图表标题 plot_widget.setTitle("温度变化曲线", color='b', size='14pt') # 设置坐标轴标签 plot_widget.setLabel('left', '温度', '°C') plot_widget.setLabel('bottom', '时间', 's') # 显示网格 plot_widget.showGrid(x=True, y=True, alpha=0.3) # 生成示例数据并绘图 x = np.linspace(0, 10, 100) y = np.sin(x) # 绘制一条红色、带圆形标记的曲线,并命名为"示例曲线" plot_widget.plot(x, y, pen='r', symbol='o', symbolSize=5, name='示例曲线') # 添加图例 plot_widget.addLegend() plot_widget.show() sys.exit(app.exec_()) -
视图控制与交互
通过设置视图范围和使用信号,可以实现图表的自动缩放或联动。
python# 将X轴范围锁定在0到5,Y轴范围锁定在-1.5到1.5,并且不留边距(padding=0) plot_widget.setXRange(0, 5, padding=0) plot_widget.setYRange(-1.5, 1.5, padding=0) # 连接信号,当视图范围改变时在控制台打印新范围 def on_x_range_changed(view, range_tuple): print(f"X轴范围变为: {range_tuple}") plot_widget.sigXRangeChanged.connect(on_x_range_changed) -
动态数据更新
对于实时数据展示,高效的方法是更新已有数据项,而非清除重绘。
python# 初始绘制一条空曲线,并保存其引用 curve = plot_widget.plot(pen='b') # 初始化数据容器 data_x = [] data_y = [] # 模拟数据更新函数 def update_data(new_value): data_x.append(len(data_x)) # 假设X轴是数据点索引 data_y.append(new_value) # 高效更新曲线数据 curve.setData(data_x, data_y)
效果如图:

实用技巧与进阶概念
掌握了基本操作后,了解一些进阶概念和技巧能让你的图表更出色。
-
理解底层架构 :
PlotWidget是一个高级封装,其内部核心是一个PlotItem,而PlotItem又包含一个负责实际显示和交互的ViewBox。当你调用plot_widget.plot()时,实际上是在其内部的PlotItem上操作。这种设计使得PlotWidget既易用又强大。 -
线条与标记样式 :通过
pg.mkPen()和pg.mkBrush()可以创建更复杂的线条和填充样式。python# 创建自定义的笔(Pen):蓝色、2像素宽、虚线 custom_pen = pg.mkPen(color='b', width=2, style=pg.QtCore.Qt.DashLine) # 创建自定义的画刷(Brush):绿色填充 custom_brush = pg.mkBrush('g') plot_widget.plot(x, y, pen=custom_pen, symbol='s', symbolBrush=custom_brush) -
多图表布局 :如果需要在一个窗口中排列多个图表,可以使用
GraphicsLayoutWidget,它类似于一个网格布局,可以轻松地添加和管理多个PlotItem。pythonlayout_widget = pg.GraphicsLayoutWidget() plot1 = layout_widget.addPlot(row=0, col=0, title="图表1") plot2 = layout_widget.addPlot(row=0, col=1, title="图表2") plot3 = layout_widget.addPlot(row=1, col=0, colspan=2, title="图表3") # 合并两列
高级功能与应用
-
实时数据更新:这是PyQtGraph的强项。正确做法是更新已有数据项,而非重绘 。
python# 初始化时获取曲线引用 self.curve = plot_widget.plot(pen='y') # ... 数据更新逻辑 new_y = np.sin(new_x) self.curve.setData(new_x, new_y) # 高效更新数据 -
鼠标交互与事件:默认支持缩放和平移。还可以连接鼠标事件实现点击添加点等高级交互 。
python# 连接鼠标点击事件示例 def on_click(event): pos = event.scenePos() # 将场景坐标转换为数据坐标... plot_widget.scene().sigMouseClicked.connect(on_click)
实用技巧
-
性能优先 :处理海量数据或需要高频实时更新时,
PlotWidget是理想选择 。 -
理解层次 :明确
PlotWidget(容器) 、PlotItem(图表管理) 和ViewBox(数据视图) 的分工,有助于解决复杂问题 。 -
善用示例 :通过运行
import pyqtgraph.examples; pyqtgraph.examples.run()来探索大量现成案例 。
扩展
PlotWidget是如何体现GraphicsView、GraphicsScene、GraphicsItem这三个核心组件交互的
PlotWidget 的精妙之处在于,它作为一个高度集成的高级组件,将 Qt Graphics View 框架中三个核心组件------GraphicsView(视图)、GraphicsScene(场景)和 GraphicsItem(图元)的复杂交互封装了起来,为我们提供了一个开箱即用、功能强大的绘图界面。
为了更直观地理解这三者是如何在 PlotWidget 内部协同工作的,我们可以参考下面的协作流程图:

下面我们来详细解读这个协作过程。
核心交互流程
1. 视图(GraphicsView):交互的窗口
PlotWidget 本身继承自 GraphicsView,它充当了观察窗口的角色。
-
职责:负责将不可见的场景内容可视化显示在屏幕上,并处理最基础的鼠标缩放、平移、键盘事件等用户交互。
-
在PlotWidget中的体现 :当你创建一个 PlotWidget 时,就已经创建了一个"准备好了"的视图窗口。你无需手动创建
QGraphicsView,PlotWidget 已经包含了它。
2. 场景(GraphicsScene):图元的舞台
PlotWidget 内部自动创建并管理着一个 PlotItem(它本身是一种特殊的 GraphicsItem),而 PlotItem又包含一个 ViewBox和一个默认的 GraphicsScene。
-
职责 :
GraphicsScene是一个不可见的容器和管理者 。它不负责绘制,而是管理所有添加到其中的图元(GraphicsItem),处理事件的派发(比如将鼠标点击事件传递给正确的图元),并管理图元的状态(如选择状态)。 -
在PlotWidget中的体现 :当你调用
PlotWidget.plot()方法绘制一条曲线时,曲线(一个PlotDataItem)实际上是被添加到了这个内部的场景中。场景负责维护这条曲线和其他所有图元(如坐标轴、网格、标签)的层次和关系。
3. 图元(GraphicsItem):真正的内容
在场景中显示的每一个独立元素都是一个图元。
-
职责 :这是具体的内容绘制者 。一条曲线、一个数据点、一段文字、一个坐标轴刻度,都可以是单独的图元。它们知道自己如何被绘制(通过重写
paint()方法),并能响应发生在其自身范围内的事件。 -
在PlotWidget中的体现 :
PlotWidget.plot()方法会创建并返回一个PlotDataItem(它是GraphicsItem的子类),它就是你看到的那条曲线。同样,坐标轴(AxisItem)、图例等也都是图元。
协作实例:一次鼠标点击的旅程
假设你在 PlotWidget 的曲线图上点击了一下鼠标,这个过程清晰地展示了三者的协作:
-
视图接收 :
PlotWidget(作为GraphicsView)首先接收到原始的鼠标点击视图坐标(以像素为单位,原点在视图左上角)。 -
坐标转换 :
PlotWidget使用mapToScene()函数将视图坐标转换为场景坐标。 -
事件派发 :转换后的事件被传递给内部的
GraphicsScene。 -
定位图元 :
GraphicsScene根据场景坐标,查询哪个(些)图元位于点击位置之下(例如,你的曲线图元),这就是所谓的碰撞检测。 -
图元响应 :事件被派发给命中了的曲线图元(
PlotDataItem)。这个图元可以触发相应的动作,例如发射一个包含点击位置数据坐标的信号,或者改变自身外观以示被选中。
开发者视角的简化
对于我们开发者而言,PlotWidget 的伟大之处在于它将底层交互封装成了简单的 API。在绝大多数情况下,你不需要直接操作 GraphicsScene或底层的 GraphicsItem。
-
添加内容 :使用
PlotWidget.plot(),PlotWidget.addItem()等方法。PlotWidget 会帮你处理将这些图元添加到正确场景的一切事宜。 -
设置样式 :直接调用
PlotWidget的方法,如setBackground(),showGrid(),setLabel()。这些调用最终都会由 PlotWidget 传递给内部对应的场景和图元(如坐标轴图元)来执行。 -
获取内部组件 :在需要更高级控制时,你可以通过
PlotWidget.getPlotItem(),PlotWidget.getViewBox(),PlotWidget.scene()等方法来获取内部的组件,从而进行深度定制。
总结
简单来说,PlotWidget 是一个"导演",它搭建了一个完整的演出舞台(整合了 Scene 和 View),并提供了丰富的"剧本"(API)。而我们开发者就像"制片人",只需要下达指令("在这里画一条正弦曲线"),导演就会指挥演员(GraphicsItem)在舞台上的正确位置进行表演,并处理好观众(用户)与演员之间的所有互动。
希望这些介绍能帮助你更好地理解和使用 PlotWidget。它是一个在功能、易用性和性能之间取得了出色平衡的工具,非常适合用于构建交互式科学计算应用程序的图形界面。