很多 PDF 自动化任务并不只是“把字写上去”这么简单。做报表时要画分隔线,做设计标注时要框选区域,做模板文档时还可能需要加椭圆、路径图形甚至半透明叠加效果。要把这些操作放进批量生成流程里,核心不是会不会画,而是能不能把坐标、样式和复用方式控制稳定。
这篇文章按“环境准备 → 基础图形 → 复杂路径 → 透明度 → 综合示例”的顺序整理 Spire.PDF 的主要绘图能力。看完之后,你可以判断这个库适不适合自己的 PDF 标注、报表生成或模板排版场景,也能直接拿代码改成可用脚本。
为什么要用代码绘制 PDF 图形
相比手动在 PDF 或设计工具里拖拽图形,用 Python 生成图形更适合重复性强、参数明确的场景,原因主要有三点:
- 精确控制:坐标、尺寸、颜色、线宽、透明度都由参数定义,适合对齐要求严格的版式。
- 批量生成:结合循环和条件逻辑,可以一次性生成大量带标注、边框或装饰元素的 PDF。
- 动态适配:图形可以随数据变化自动调整,例如根据数值改变矩形高度,或按内容区域重新计算分隔线位置。
如果你的需求是报表分区、模板标注、证书装饰线、可视化标记层,这类方式通常比手工处理更稳。
先准备库和画布坐标系
文中使用的库是 Spire.PDF。安装命令如下:
pip install Spire.PDF
这个库不只负责绘图,也提供页面管理、文字渲染等能力。对绘图来说,最关键的是理解它的画布模型:
- 所有绘图操作都在页面的
PdfCanvas对象上完成。 - 坐标原点位于页面左下角。
- 单位是点(point),
1点 = 1/72英寸。
后面无论是画线、画矩形还是做路径变换,都是基于这一套坐标系工作。
基础图形怎么画
绘制直线
直线使用 DrawLine() 完成,只需要指定起点和终点坐标。下面这段代码同时画了一条水平线和一条斜线:

from spire.pdf.common import *
from spire.pdf import *
# 创建 PDF 文档
doc = PdfDocument()
page = doc.Pages.Add()
# 保存画布状态
state = page.Canvas.Sa ve()
# 创建画笔(黑色,线宽 1 点)
pen = PdfPen(PdfRGBColor(Color.get_Black()), 1.0)
# 绘制一条从 (50, 100) 到 (400, 100) 的水平线
page.Canvas.DrawLine(pen, 50.0, 100.0, 400.0, 100.0)
# 绘制一条从 (50, 100) 到 (225, 300) 的斜线
pen2 = PdfPen(PdfRGBColor(Color.get_Red()), 1.0)
page.Canvas.DrawLine(pen2, 50.0, 100.0, 225.0, 300.0)
# 恢复画布状态
page.Canvas.Restore(state)
# 保存文档
doc.Sa veToFile("DrawLines.pdf")
doc.Close()
PdfPen 用来控制线条颜色和宽度;DrawLine() 的前两个数值是起点坐标,后两个数值是终点坐标。这里还保留了 Sa ve() 和 Restore() 的调用方式,虽然只是简单示例,但在实际项目里这是很值得保留的习惯,能减少后续样式设置互相影响的问题。
绘制虚线
虚线常用于区域分隔和范围标注。Spire.PDF 里可以通过 DashStyle 和 DashPattern 控制:
# 创建红色画笔,线宽 3 点 pen = PdfPen(PdfRGBColor(Color.get_Red()), 3.0) # 设置虚线样式 pen.DashStyle = PdfDashStyle.Dash pen.DashPattern = [1, 4, 1] # 虚线模式:1点实线、4点空白、1点实线 # 绘制虚线 page.Canvas.DrawLine(pen, 50.0, 200.0, 400.0, 200.0)
PdfDashStyle 提供了 Dash、Dot、DashDot 等预设样式;如果预设不够用,再通过 DashPattern 自定义节奏。像 [1, 4, 1] 这种数组,本质上就是按“实线长度 - 空白长度 - 实线长度”的方式循环绘制。
绘制矩形
矩形是 PDF 标注场景里使用频率最高的图形之一。它既可以只画边框,也可以同时填充颜色:
# 绘制矩形边框 pen = PdfPen(PdfRGBColor(Color.get_Black()), 0.5) # 参数:画笔、x、y、宽度、高度 page.Canvas.DrawRectangle(pen, 100.0, 150.0, 200.0, 120.0) # 绘制带填充色的矩形 pen2 = PdfPen(PdfRGBColor(Color.get_Black()), 1.0) brush = PdfSolidBrush(PdfRGBColor(Color.get_OrangeRed())) rect = RectangleF(PointF(100.0, 300.0), SizeF(200.0, 120.0)) page.Canvas.DrawRectangle(pen2, brush, rect)
DrawRectangle() 常见有两种用法:一种直接传入 x、y、宽度和高度,只画轮廓;另一种配合 PdfBrush 一起使用,既画边框又填充内部颜色。这里的 PdfSolidBrush 是最基础也最常用的填充方式。
绘制椭圆和圆形
椭圆通常用于辅助标注、流程节点或局部高亮。对应的方法是 DrawEllipse():
# 绘制椭圆边框(以矩形边界定义椭圆范围) pen = PdfPen(PdfRGBColor(Color.get_CadetBlue()), 1.0) # 参数定义外接矩形的范围,椭圆会被绘制在该矩形内部 page.Canvas.DrawEllipse(pen, 220.0, 320.0, 100.0, 90.0) # 绘制填充椭圆 brush = PdfSolidBrush(PdfRGBColor(Color.get_CadetBlue())) page.Canvas.DrawEllipse(brush, 380.0, 325.0, 80.0, 80.0) # 第三个和第四个参数分别控制水平半径和垂直半径 # 当两者相等时即为正圆 page.Canvas.DrawEllipse(brush, 100.0, 450.0, 50.0, 50.0) # 这行会绘制一个正圆
这里可以直接抓住一个要点:椭圆不是单独定义出来的,而是放在外接矩形内部。外接矩形越接近正方形,图形就越接近正圆。
复杂图形怎么用路径拼出来
当直线、矩形和椭圆不够用时,就需要借助 PdfPath。它适合处理五角星、多边形或其他需要由多条线段和曲线组合的图形。

import math
# 计算五边形的五个顶点
points = [None] * 5
for i in range(5):
x = float(math.cos(i * 2 * math.pi / 5))
y = float(math.sin(i * 2 * math.pi / 5))
points[i] = PointF(x, y)
# 创建路径并添加线段
path = PdfPath()
path.AddLine(points[2], points[0])
path.AddLine(points[0], points[3])
path.AddLine(points[3], points[1])
path.AddLine(points[1], points[4])
path.AddLine(points[4], points[2])
# 绘制路径轮廓
pen = PdfPen(PdfRGBColor(Color.get_DeepSkyBlue()), 0.02)
page.Canvas.ScaleTransform(50.0, 50.0)
page.Canvas.TranslateTransform(5.0, 5.0)
page.Canvas.DrawPath(pen, path)
# 绘制填充路径
brush = PdfSolidBrush(PdfRGBColor(Color.get_DeepSkyBlue()))
page.Canvas.DrawPath(pen, brush, path)
PdfPath 的价值在于“先定义路径,再统一绘制”。除了 AddLine(),还可以继续使用 AddArc()、AddCurve() 等方法拼出更复杂的轮廓。
这一段代码还顺带展示了两个很重要的变换操作:
ScaleTransform():缩放当前坐标系,让小尺寸路径按比例放大。TranslateTransform():平移坐标系,把同一个图形移动到新位置。
如果你要在一页里重复放置同一种图标或标记,这种做法会比手工重算每个点坐标更省事。
图形叠加时如何控制透明度
多个图形叠加时,透明度控制会直接影响可读性。Spire.PDF 通过 SetTransparency() 处理这个问题:

# 设置透明度(参数范围 0.0~1.0,0.0 完全透明,1.0 不透明) page.Canvas.SetTransparency(0.5, 0.5) # 在此之后绘制的图形将以 50% 透明度显示 pen = PdfPen(PdfRGBColor(Color.get_Black()), 1.0) brush = PdfSolidBrush(PdfRGBColor(Color.get_Red())) page.Canvas.DrawRectangle(pen, brush, RectangleF(PointF(200.0, 300.0), SizeF(200.0, 100.0))) # 设置不同的透明度 page.Canvas.SetTransparency(0.2, 0.2) page.Canvas.DrawRectangle(pen, brush, RectangleF(PointF(300.0, 250.0), SizeF(200.0, 100.0)))
这里的参数范围是 0.0~1.0:0.0 表示完全透明,1.0 表示完全不透明。它特别适合做高亮遮罩、重叠标注区、设计审阅层这类需要“看得到下面内容”的场景。
完整示例:把常见图形放到同一个 PDF 页面
下面这段示例把前面的直线、虚线、矩形、椭圆组合到一个页面中,适合直接作为起步模板:
from spire.pdf.common import *
from spire.pdf import *
import math
# 创建文档
doc = PdfDocument()
page = doc.Pages.Add()
# 保存画布状态
state = page.Canvas.Sa ve()
# 1. 绘制直线
pen = PdfPen(PdfRGBColor(Color.get_Black()), 1.0)
page.Canvas.DrawLine(pen, 50.0, 50.0, 200.0, 50.0)
# 2. 绘制虚线
pen_dash = PdfPen(PdfRGBColor(Color.get_Red()), 2.0)
pen_dash.DashStyle = PdfDashStyle.Dash
page.Canvas.DrawLine(pen_dash, 50.0, 80.0, 200.0, 80.0)
# 3. 绘制矩形边框
pen_rect = PdfPen(PdfRGBColor(Color.get_Blue()), 1.0)
page.Canvas.DrawRectangle(pen_rect, 50.0, 120.0, 150.0, 100.0)
# 4. 绘制填充矩形
pen_fill = PdfPen(PdfRGBColor(Color.get_Black()), 0.5)
brush_fill = PdfSolidBrush(PdfRGBColor(Color.get_OrangeRed()))
page.Canvas.DrawRectangle(pen_fill, brush_fill,
RectangleF(PointF(50.0, 250.0), SizeF(150.0, 100.0)))
# 5. 绘制椭圆
brush_ellipse = PdfSolidBrush(PdfRGBColor(Color.get_CadetBlue()))
page.Canvas.DrawEllipse(brush_ellipse, 300.0, 120.0, 100.0, 80.0)
# 6. 绘制正圆
page.Canvas.DrawEllipse(brush_ellipse, 300.0, 250.0, 60.0, 60.0)
# 恢复画布状态
page.Canvas.Restore(state)
# 保存
doc.Sa veToFile("ShapesDemo.pdf")
doc.Close()
如果你只是想快速验证环境是否正常,这段综合代码比逐个方法单独测试更有效。能顺利输出 ShapesDemo.pdf,通常就说明基础绘图流程已经打通。
总结:哪些场景最适合用这套方法
从能力边界看,Spire.PDF 已经覆盖了大部分常见 PDF 图形绘制需求:基础线条、虚线样式、矩形与填充、椭圆与圆形、自定义路径,以及叠加时的透明度控制。
如果你的工作偏向报表生成、模板标注、证书装饰、审阅批注层,这套方法足够直接;如果后续还要做更复杂的视觉效果,可以继续往渐变填充、更多路径方法、坐标变换和图层组织方向深入。









