Python系列 之 ReportLab库 pdfgen模块Canvas对象绘制图形和文本

Python系列 之 ReportLab库 pdfgen模块Canvas对象绘制图形和文本,第1张

Python系列 之 ReportLab库 pdfgen模块Canvas对象绘制图形和文本
  • ReportLab库
  • pdfgen模块
    • Canvas对象
    • 关于注册字体(中文显示问题)
    • Canvas对象的绘制 *** 作
      • showPage方法
      • save方法
      • 设置字体
      • 绘制字符串
      • 绘制直线
      • 绘制形状
      • 绘制图片
      • 设置颜色
      • 设置线条样式
      • 改变几何形态
      • 状态控制
      • 用text object绘制
      • 用path object绘制
      • Canvas对象的其他方法

ReportLab库 pdfgen模块

pdfgen包是生成PDF文档的最低级别接口,用于将文档“绘制”到一系列页面上。提供绘制 *** 作的接口对象是pdfgen.canvas.Canvas对象

Canvas对象

Canvas对象可以把它当做一张白纸,纸上的点使用笛卡尔(X,Y)坐标进行标识,默认情况下,(0,0)原点位于页面的左下角。另外,默认情况下,第一个坐标x向右移动,第二个坐标y向上移动。
实例化一个Canvas对象:

from reportlab.pdfgen import canvas
# 参数
# filename 最终的PDF文件名
# pagesize 两个点数的tuple 用来定义页面大小,默认是A4大小
# 在reportlab.lib.pagesize中定义了letter,A4等页面大小
# bottomup将来可能会被放弃 为了转换坐标
# pageCompression 是否对PDF *** 作进行压缩,默认情况下不被压缩,压缩会减慢运行速度\
# 如果页面有大量的文本和矢量图形的话压缩会节省空间
# encrypt 如果赋值一个字符串的话 将会作为PDF的用户密码使用
cav = canvas.Canvas(
            filename=filename, pagesize=None, bottomup=1,
            pageCompression=1, encrypt=None)

有了Canvas对象,就可以使用对象的绘制方法将内容绘制在PDF文档的页面中,下面介绍Canvas对象的一些绘制方法

关于注册字体(中文显示问题)

如果想要写入中文文本是必须要注册支持中文的字体,要不然是无法显示绘制的中文的:

from reportlab.pdfbase import pdfmetrics, ttfonts
# simsun字体文件的存放路径
simsun_FONT_PATH = "./fonts/simsun.ttc"
# 注册字体解决中文显示问题
# TTFont方法的参数:
# name 需要注册字体的名称(psfontname) 
# filename 字体存放的路径
font = ttfonts.TTFont(name="simsun", filename=simsun_FONT_PATH)
pdfmetrics.registerFont(font=font)
# 后续使用setFont方法设置字体显示
# setFont方法的psfontname参数调用TTFont的name也就是'simsun'
Canvas对象的绘制 *** 作 showPage方法

showPage方法用来结束一个页面的绘制;
在完成当前页面绘制的同时,保存Canvas对象绘制的当前页面内容,如果后续有新的绘制将在下一个页面进行;
需要注意的是当前设置的字体 颜色 旋转等样式在一下一个页面都会进行重置,也就是这些样式在各个页面之间都是不进行传递的

cav.showPage()
save方法

当所有的PDF页面都绘制完成后需要调用Canvas对象的save方法来进行保存到本地磁盘,保存的文件就是Canvas对象的filename参数

cav.save()
设置字体

setFont方法
setFont方法可以设置字体的字体名称以及大小

# 设置字体方法
# setFont(psfontname, size, leading=None)
# psfontname 字体名称 size 字体大小 leading 行间距
# psfontname 可以使用 registerFont方法注册的TTFont对象的name
cav.setFont(psfontname="simsun", size=10, leading=1)
绘制字符串

在PDF页面上绘制字符串内容,drawString,drawRightString和drawCentredString等方法,都是用来绘制字符串内容的方法

方法说明
drawString以X坐标为起点进行绘制
drawRightString以X坐标为终点进行绘制
drawCentredString以X坐标为中心进行绘制

drawString方法
drawString方法用来在页面的指定位置进行绘制字符串内容
字符以X坐标为起点进行绘制

# 设置字体 字体名称和字体大小
cav.setFont(psfontname="simsun", size=10, leading=1)
# drawString(x, y, text, mode=None, charSpace=0, direction=None, wordSpace=None)
# 参数 x=x坐标 y=y坐标 text=绘制的内容 str
text = "ReportLab库的学习"
x = 300
y = 420
cav.drawString(x=x, y=y, text=text)

drawRightString方法
drawRightString 绘制与X坐标右对齐的字符串;也就是以X坐标为终点

# drawRightString(x, y, text, mode=None, charSpace=0, direction=None, wordSpace=None)
cav.drawRightString(x, y-10, "drawRightString "+text)

drawCentredString方法
drawCentredString 绘制以X坐标为中心的字符串

# drawCentredString(x, y, text, mode=None, charSpace=0, direction=None, wordSpace=None)
cav.drawCentredString(x, y-20, "drawCentredString "+text)

绘制直线

绘制直线的方法line和lines

方法说明
line提供两个点的坐标,绘制一条直线
lines提供一组坐标list,绘制多条直线

line方法
每次绘制一条直线

# line(x1, y1, x2, y2)
# x1和y1 作为起点坐标 x2和y2 作为终点坐标 画一条直线
cav.line(x1=300, y1=400, x2=300, y2=550)
cav.drawCentredString(x=300, y=390, text="line方法")

lines方法
可以绘制多条直线

# 存放多条线的坐标
crosshairs = [(350, 550, 400, 550),
              (350, 500, 450, 500),
              (350, 450, 500, 450),
              (350, 400, 550, 400), ]
# 画多条线 参数 linelist 存放多条线的坐标
cav.lines(linelist=crosshairs)
cav.drawCentredString(x=450, y=380, text="lines方法")

以上就是Canvas对象绘制直线的方法:
再执行showPage()和save()方法就会对PDf文件进行保存

cav.showPage()
cav.save()

绘制形状
方法说明
grid根据一组X坐标和一组Y坐标绘制网格
rect绘制矩形
circle绘制一个圆形
roundRect绘制一个圆角的矩形
arc根据矩形坐标内绘制一个指定角度的椭圆
ellipse在一个封闭的矩形坐标内绘制一个椭圆
wedge绘制一个楔形

grid方法
grid 方法 绘制网格 ; 根据xlist=X轴坐标list 和 ylist=Y轴坐标list;
其中 xlist和ylist都必须至少2个元素

# 设置字体 字体名称和字体大小
cav.setFont(psfontname="simsun", size=10, leading=1)
# grid(xlist, ylist)
# grid 绘制网格  xlist X轴坐标list  ylist Y轴坐标list
# 源码:grid方法主要逻辑:
#-------+++++++++++----------
# lines = []
# y0, y1 = ylist[0], ylist[-1]
# x0, x1 = xlist[0], xlist[-1]
# for x in xlist:
#     lines.append((x, y0, x, y1))
# for y in ylist:
#     lines.append((x0, y, x1, y))
# Canvas.lines(lines)
#-------+++++++++++----------

xlist = [50, 150, 200, 300]
ylist = [800, 750, 700, 650]
cav.grid(xlist=xlist, ylist=ylist)
cav.drawCentredString(x=175, y=810, text="grid方法")

rect方法
rect方法绘制矩形,根据一个坐标点,以及给出的宽度和高度绘制,根据给出的宽度和高度的数值可以决定左右和上下的绘制方向

# rect 绘制矩形
# rect(x, y, width, height, stroke=1, fill=0)
# x, y 坐标点
# width 矩形宽度 正数 向右绘制,负数 向左绘制
# height 矩形高度 正数 向上绘制,负数 向下绘制
# stroke 是否显示边框 1 显示 0 不显示 默认显示
# fill 是否对矩形区域填充 1 填充 0 不填充 默认不填充
cav.rect(x=350, y=800, width=200, height=-150, stroke=1, fill=0)
cav.drawCentredString(x=450, y=810, text="rect方法")

circle方法
circle方法根据给定的圆心坐标以及圆的半径绘制一个圆形

# circle 绘制一个圆形 x_cen 圆心的X坐标 y_cen圆心的Y坐标 r 圆的半径
# circle( x_cen, y_cen, r, stroke=1, fill=0)
# x_cen, y_cen 圆心的X Y 坐标
# r 圆的半径 
# stroke 边框
# fill 填充
cav.circle(x_cen=175, y_cen=500, r=120, stroke=1, fill=0)
cav.drawCentredString(x=175, y=630, text="circle方法")

roundRect方法
roundRect 绘制一个圆角的矩形

# roundRect 绘制一个圆角的矩形 radius参数是矩形四个角圆形的半径 类似CSS的border-radius?
# roundRect(x, y, width, height, radius, stroke=1, fill=0)
# 参数 同 rect方法
cav.roundRect(x=350, y=620, width=200, height=-240, radius=50, stroke=1, fill=0)
cav.drawCentredString(x=450, y=630, text="roundRect方法")

arc方法
arc 在矩形x1,y1,x2,y2内画一个指定角度的椭圆

# arc 在矩形x1,y1,x2,y2内画一个椭圆 从startAng度开始逆时针画extent度
# arc(x1, y1, x2, y2, startAng=0, extent=90)
# 由x1, y1, x2, y2组成的矩形,从startAng(默认0)开始逆时针画extent度(默认90)
cav.arc(x1=50, y1=10, x2=300, y2=330, startAng=90, extent=270)
cav.drawCentredString(x=175, y=340, text="arc方法")
cav.drawCentredString(x=175, y=320, text="startAng=90")
cav.drawCentredString(x=300, y=175, text="extent=270")

wedge方法
wedge 绘制一个楔形 扇形 和arc类似

# wedge 绘制一个楔形 扇形  参数同arc
# wedge(x1, y1, x2, y2, startAng, extent, stroke=1, fill=0)
cav.wedge(x1=350, y1=175, x2=550, y2=330, startAng=0, extent=200)
cav.drawCentredString(x=450, y=340, text="wedge方法")

ellipse方法
ellipse 在一个封闭的矩形内绘制一个椭圆

# ellipse(x1, y1, x2, y2, stroke=1, fill=0)
# ellipse 在一个封闭的矩形内绘制一个椭圆
cav.ellipse(x1=350, y1=10, x2=550, y2=165, stroke=1, fill=0)
cav.drawCentredString(x=450, y=175, text="ellipse方法")


以上就是Canvas对象的绘制形状的方法:
绘制完成后的调用showPage()和save()方法:

cav.showPage()
cav.save()

最后页面截图

绘制图片

drawImage方法
drawImage方法可以在页面中绘制图片

# drawImage(image, x, y, width=None, height=None, mask=None,preserveAspectRatio=False, anchor='c', anchorAtXY=False, showBoundary=False)
# 参数
# image 一个ImageReader对象或者一个图片的文件名称
# width|height 定义绘制图片的尺寸

# image_path 图片路径作为drawImage方法的image参数值
image_path = "./img/logo2.png"
img = Image.open(image_path)
width, height = img.size
cav.drawImage(image=image_path, x=10, y=10, width=width*0.8, height=height*0.8,
              mask=None, preserveAspectRatio=False, anchor='c',
              anchorAtXY=False, showBoundary=True)

# 一个ImageReader对象作为drawImage方法的image参数值
from reportlab.lib.utils import ImageReader
from io import BytesIO
image_path = "./img/logo.png"
img = Image.open(image_path)
width, height = img.size
img_io = BytesIO()
img.save(img_io, 'png')
image = ImageReader(img_io)
cav.drawImage(image=image, x=10, y=360, width=width, height=height,
              mask=None, preserveAspectRatio=False, anchor='c',
              anchorAtXY=False, showBoundary=True)

设置颜色
方法说明
setFillColorCMYK使用减色模式填充区域
setStrokeColorCMYK使用减色模式填充边框
setFillColorRGB使用RGB模式填充区域
setStrokeColorRGB使用RGB模式填充边框
setFillGray设置灰度
setStrokeGray设置灰度
setFillColor根据颜色对象填充区域
setStrokeColor根据颜色对象填充边框
setFillAlpha设置填充区域的透明度
setStrokeAlpha设置填充边框的透明度

setFillColorCMYK和setStrokeColorCMYK方法
CMYK模式是减色模式,相对应的RGB模式是加色模式
C:Cyan = 青色,又称为‘天蓝色’或是‘湛蓝’;M:Magenta = 品红色,又称为‘洋红色’;Y:Yellow = 黄色;K:blacK=黑色,虽然有文献解释说这里的K应该是Key Color(定位套版色),但其实是和制版时所用的定位套版观念混淆而有此一说。此处缩写使用最后一个字母K而非开头的B,是为了避免与Blue混淆
使用减色模式填充 接受4个介于0.0和1.0之间的参数:从0-1颜色依次加深

# setFillColorCMYK(c, m, y, k, alpha=None)
# setStrokeColorCMYK(c, m, y, k, alpha=None)
# 参数 alpha 设置填充的透明度
cav.setFillColorCMYK(c=0.5, m=0.1, y=0.1, k=0.1, alpha=0.1)
cav.setStrokeColorCMYK(c=0.5, m=0.1, y=0.1, k=0.1, alpha=None)

以setFillColorCMYK方法示例:

dx_cen = 0
x_cen = 50+dx_cen
y_cen = 750
r = 25
for cmyk in [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1), (0, 0, 0, 0)]:
    c, m, y, k = cmyk
    cav.setFillColorCMYK(c, m, y, k, alpha=0.8)
    cav.circle(x_cen=x_cen+dx_cen, y_cen=y_cen, r=r, fill=1)
    cav.setFillColorCMYK(c=0, m=0, y=0, k=1)
    cav.drawCentredString(x=x_cen+dx_cen, y=y_cen+r+10, text=f"CMYK:{cmyk}")
    dx_cen += 120

setFillColorRGB和setStrokeColorRGB方法
RGB是代表红、绿、蓝三个通道的颜色;setFillColorRGB和setStrokeColorRGB方法使用RGB模式进行颜色填充

# setFillColorRGB(r, g, b, alpha=None)
# setStrokeColorRGB(r, g, b, alpha=None)
cav.setFillColorRGB(r=0.5, g=0.5, b=0.5, alpha=None)
cav.setStrokeColorRGB(r=1, g=1, b=1, alpha=None)

以setFillColorRGB方法示例:

dx_cen = 0
x_cen = 50+dx_cen
y_cen = 650
R = 25
for rgb in [(1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 0, 0), (1, 1, 1)]:
    r, g, b = rgb
    cav.setFillColorRGB(r, g, b)
    cav.circle(x_cen=x_cen+dx_cen, y_cen=y_cen, r=R, fill=1)
    cav.setFillColorRGB(r=0, g=0, b=0)
    cav.drawCentredString(x=x_cen+dx_cen, y=y_cen+R+10, text=f"RGB:{rgb}")
    dx_cen += 120


setFillGray和setStrokeGray方法
设置灰度模式 ;0.0=黑色,1.0=白色 即 由 0-1 从 黑→灰→白过渡

# setFillGray(gray, alpha=None)
# setStrokeGray(gray, alpha=None)
cav.setFillGray(gray=0)
cav.setStrokeGray(gray=1)

以setFillGray方法示例

dx_cen = 0
x_cen = 50+dx_cen
y_cen = 550
R = 25
for gray in [0, 0.2, 0.4, 0.6, 0.8, 1]:
    cav.setFillGray(gray=gray)
    cav.circle(x_cen=x_cen+dx_cen, y_cen=y_cen, r=R, fill=1)
    cav.setFillGray(gray=0)
    cav.drawCentredString(x=x_cen+dx_cen, y=y_cen+R+10, text=f"Gray:{gray}")
    dx_cen += 100

setFillColor和setStrokeColor方法
setFillColor和setStrokeColor方法接受一个颜色对象作为参数,根据颜色对象进行填充

# setFillColor(aColor, alpha=None)
# setStrokeColor(aColor, alpha=None)
# 参数 aColor 可以是 CMYKColor对象、Color对象、tuple、list 或者 Str,colors模块下颜色常量
# aColor 如果是Str类型则通过toColor对象转换
from reportlab.lib import colors
# aColor == CMYKColor对象
aColor = colors.CMYKColor(cyan=0.1, magenta=0.5,
                          yellow=0.6, black=0.1,
                          spotName=None, density=1,
                          knockout=None, alpha=1)
# aColor == list or tuple
# list or tuple 的长度 只能是3(RGB)或者4(CYMK) 否则引发 ValueError
aColor = (0.2, 0.3, 0.4)
# aColor == Color对象
aColor = colors.Color(red=0.5, green=0.6, blue=0.7)
# aColor == Str
# aColor 如果是Str类型则通过toColor对象转换
# 'rgb(50 %, 0%, 0%)' 'rgba(255, 0, 0, 0.5)'
aColor = 'rgba( 255,0,0,0.5)'
# colors模块下颜色常量
# aColor = colors.darkgray
cav.setFillColor(aColor=aColor, alpha=None)
cav.setStrokeColor(aColor=aColor, alpha=None)

setFillAlpha和setStrokeAlpha方法
设置填充的透明度

# setFillAlpha(a)
# setStrokeAlpha(a)
# 参数 a == isinstance(a,(float,int)) and 0<=a<=1
cav.setFillAlpha(a=0.5)
cav.setStrokeAlpha(a=0.2)
设置线条样式
方法说明
setLineWidth设置线条宽度
setLineCap设置线条顶端样式
setLineJoin设置线条相交方式
setMiterLimit设置斜接长度限制
setDash置线条类型 将线拆分为点或破折号

setLineWidth方法
设置线条宽度

# setLineWidth(width)
cav.setLineWidth(width=5)

setLineCap方法
设置线条顶端样式

# setLineCap(mode)
# 参数mode取值:0=butt,1=round,2=square 0=对接,1=圆形,2=方形
dx = 0
mode_dict = {0: 'butt', 1: 'round', 2: 'square'}
for i in range(3):
    cav.setLineCap(mode=i)
    cav.lines(linelist=[(50+dx, 800, 100+dx, 800), (50+dx, 800, 50+dx, 700)])
    cav.drawCentredString(x=100+dx, y=810, text=f'setLineCap方法 mode={mode_dict[i]}')
    dx += 200


setLineJoin方法
设置线条相交方式

# setLineJoin(mode)
# setLineJoin设置线条相交方式 参数mode取值:0=mitre, 1=round, 2=bevel 0=斜接,1=圆形,2=斜面
dx = 0
mode_dict = {0: 'mitre', 1: 'round', 2: 'bevel'}
for i in mode_dict.keys():
    cav.setLineJoin(mode=i)
    cav.wedge(x1=50+dx, y1=400, x2=100+dx,
              y2=600, startAng=0, extent=90)    
    cav.drawCentredString(x=100+dx, y=610, text=f'setLineJoin方法 mode={mode_dict[i]}')
    dx += 200
    


setMiterLimit方法
设置斜接长度限制
只是在setLineJoin的mode=0=mitre模式下起作用:
如果斜接长度大于limit值进行切除

# setMiterLimit(limit)
# 如果斜接长度大于limit值进行切除
cav.setLineJoin(mode=0)
cav.setMiterLimit(limit=1)
cav.wedge(x1=50, y1=190, x2=100,
          y2=390, startAng=0, extent=90)
cav.drawCentredString(x=75, y=410, text=f'setLineJoin方法 mode=mitre')
cav.drawCentredString(x=75, y=400, text=f'setMiterLimit方法 limit=1')

setDash方法
setDash方法设置线条类型 将线拆分为点或破折号

# setDash(array=[], phase=0)
# 参数 array 绘制的点数 可以是一个数值 也可以是一个list
# phase 间隔不绘制的点数
dx = 0
for arr, phase in zip([6, 3, (3, 2, 1), [1, 2, 3]], [3, 3, 3, 3]):
    cav.setDash(array=arr, phase=phase)
    cav.circle(x_cen=60+dx, y_cen=100, r=30)
    cav.line(x1=30+dx, y1=50, x2=90+dx, y2=50)
    cav.drawCentredString(x=60+dx, y=140, text=f'setDash arr={arr},phase={phase}')
    dx += 150

改变几何形态
方法说明
setPageSize设置画布页面大小
transform矩阵转换
translate转移画布原点到指定位置
scale按 x y 比例缩放画布
rotate按角度旋转画布
skew错切

提示:transform, translate, scale, rotate, 和skew这些转换是增量的;新的转换不会进行替换,只会修改当前的转换

setPageSize

from reportlab.lib.pagesizes import letter
# setPageSize(size)
# letter == (612.0, 792.0)
cav.setPageSize(size=letter)

translate
转移画布原点到指定位置

# translate(dx, dy)
# 将原点移动到dx,dy
cav.drawString(0, 0, "old:(0,0) the Origin")
cav.translate(dx=50, dy=50)
cav.drawString(0, 0, "new:(0,0) the Origin")

scale
按 x y 比例缩放画布

# scale(x, y)
# scale(x, y)==transform(x, 0, 0, y, 0, 0)
# 画布缩放x, y
x, y = 300, 400
dx = dy = 0.5
cav.drawCentredString(x, y, text="x, y = %s" % ([x, y]))
cav.setFillColor(aColor="rgb(0.5,0.5,1)", alpha=0.5)
cav.circle(x, y, 150, fill=1)
cav.scale(x=dx, y=dy)
cav.circle(x, y, 150, fill=1)
cav.setFillColor(aColor="black", alpha=0.5)
cav.drawCentredString(x, y, text="x, y = %s" % ([x*dx, y*dy]))

rotate
将画布旋转theta

# rotate(theta)
# c = cos(theta * pi / 180)
# s = sin(theta * pi / 180)
# transform(c, s, -s, c, 0, 0)
for theta in range(60):
    cav.rotate(theta=1)
    cav.line(x1=450, y1=200, x2=550, y2=200)

skew

# skew(alpha, beta) 错切
# tanAlpha = tan(alpha * pi / 180)
# tanBeta = tan(beta * pi / 180)
# transform(1, tanAlpha, tanBeta, 1, 0, 0)
cav.setFillColor(aColor="red")
cav.rect(x=300, y=10, width=25, height=50, fill=1)
cav.skew(alpha=0, beta=45)
cav.setFillColor(aColor="green")
cav.rect(x=300, y=10, width=25, height=50, fill=1)

状态控制
方法说明
saveState保持画布当前的设置
restoreState清除画布在saveState之后的设置

saveState 和restoreState只是对当前页面的设置,因为不同页面直接是不会传递对页面的样式设置
saveState方法
保持画布当前的设置

canvas.saveState() 

restoreState方法
清除画布在saveState之后的设置

canvas.restoreState()

示例:

from reportlab.lib import colors
from reportlab.lib.units import inch
# canvas.saveState()  保持画布当前的设置
# canvas.restoreState() 清除画布在saveState之后的设置
cav.setFillColor(aColor=colors.red)
# 保存画布setFillColor(aColor=colors.red)的样式状态
cav.saveState()

cav.setFillColor(aColor=colors.green)
cav.scale(2, 2)
cav.circle(x_cen=2.5*inch, y_cen=3*inch, r=1*inch, fill=1)
# 清除setFillColor(aColor=colors.green)和scale(2, 2)的样式状态
cav.restoreState()
cav.circle(x_cen=2.5*inch, y_cen=2*inch, r=1*inch, fill=1)

绘制完绿色圆形后清除了绿色颜色填充和scale转换,但是仍然保留了saveState方法之前的红色颜色填充:

用text object绘制

PDFTextObject
文本对象(PDFTextObject)提供了Canvas对象无法直接使用的文本布局参数的详细控制。此外,它会生成更小的PDF 比许多单独调用drawString方法的速度更快,通过查看canvas模块的源码你会发现,Canvas对象的drawString,drawRightString都是使用文本对象(PDFTextObject)进行实现的

文本对象的一些方法:

方法说明
setTextOrigin重置 text对象的坐标
setTextTransform与setTextOrigin类似,但有旋转、缩放等功能
moveCursor移动当前光标
getCursor获取text对象的坐标
getX获取text对象的X坐标
getY获取text对象的Y坐标
setFont设置字体
textLine绘制text 绘制完成后光标向下一行移动
textOut绘制text 绘制完成后光标不向下一行移动
textLines绘制多行 对应Python多行字符串类型
setCharSpace调整文本的字符间距
setWordSpace整单词之间的间距 中文没有测试到作用
setHorizScale水平拉伸或收缩文本行
setLeading调节行间距
setTextRenderMode设置文本呈现模式
setRise上下移动文本基线以允许实现上标/下标
setFillColor设置填充颜色
setStrokeColor设置线条颜色

文本对象(PDFTextObject)可以使用Canvas对象的beginText方法得到,
下面示例文本对象的方法使用

from reportlab.lib.units import inch
from reportlab.lib import colors
# beginText(x=0, y=0, direction=None)
textobj = cav.beginText(x=300, y=200, direction=None)
# setTextOrigin 重置 text对象的坐标或者说光标的位置
textobj.setTextOrigin(x=inch, y=2.5*inch)
# setTextTransform(a, b, c, d, e, f) 与setTextOrigin类似,但有旋转、缩放等功能
# textobj.setTextTransform(a, b, c, d, e, f)
# getCursor getX getY 获取text对象的坐标
print("getCursor()方法 获取坐标tuple", textobj.getCursor())
print("getX()方法 获取X坐标", textobj.getX())
print("getY()方法 获取Y坐标", textobj.getY())
# setFont 设置字体
textobj.setFont(psfontname="simsun", size=30, leading=None)
# 调整文本的字符间距
textobj.setCharSpace(charSpace=0.1*inch)
# 调整单词之间的间距 
textobj.setWordSpace(wordSpace=0.1*inch)
# 水平拉伸或收缩文本行
textobj.setHorizScale(horizScale=1.5*inch)
# 调节行间距
textobj.setLeading(leading=0.5*inch)
# 绘制text 绘制完成后光标向下一行移动
textobj.textLine(text="this is text object")
# 从当前光标位置进行移动光标到 X轴移动dx Y轴移动dy 后的光标位置
textobj.moveCursor(dx=20, dy=20)
# 绘制多行 对应Python多行字符串类型 trim=0 保留字符串中的空白位置 trim=1 不保留
textobj.textLines(stuff='''
                  1.第一行
                  2.第二行
                  3.第三行''', trim=1)
# 绘制text 绘制完成后光标不向下一行移动
textobj.textOut(text="setRise方法")
# 上下移动文本基线以允许上标/下标
textobj.setRise(rise=12)
textobj.textLine(text="上标")
textobj.setRise(rise=-12)
textobj.textOut(text="setRise方法")
textobj.setRise(rise=-20)
textobj.textLine(text="下标")

# 设置填充颜色
textobj.setFillColor(aColor=colors.green)
# 设置线条颜色
textobj.setStrokeColor(aColor=colors.red)
textobj.moveCursor(dx=-50, dy=0)
# textobject.setTextRenderMode(mode) 设置文本呈现模式
# 参数 mode
# 0 = Fill text  # setFillColor方法填充颜色
# 1 = Stroke text  # setStrokeColor方法填充颜色
# 2 = Fill then stroke  # setFillColor和setStrokeColor一起填充颜色
# 3 = Invisible   # 不可见
# 4 = Fill text and add to clipping path  # setFillColor方法填充颜色
# 5 = Stroke text and add to clipping path    # setStrokeColor方法填充颜色
# 6 = Fill then stroke and add to clipping path    # setFillColor和setStrokeColor一起填充颜色
# 7 = Add to clipping path
# mode == 3 or 7 在页面上看不到内容
textobj.textLine(text="setTextRenderMode方法:")
textobj.setFont(psfontname="simsun", size=50, leading=50)
for mode in range(8):
    textobj.setTextRenderMode(mode=mode)
    textobj.textLine(text=f"mode={mode}:mode")
    
# 调用Canvas对象的drawText方法完成绘制
# drawText(aTextObject)
# aTextObject == PDFTextObject对象
cav.drawText(aTextObject=textobj)

用path object绘制

path object对象(PDFPathObject)
path object类似于text object path对象提供了可以执行复杂图像绘制的方法,可以认为是手执画笔在页面上进行绘制,需要时刻跟踪画笔的落点,path object对象(PDFPathObject)可以通过Canvas对象的beginPath方法获取:

# beginPath方法 返回PDFPathObject
pathobject = cav.beginPath()

绘制完成后需要使用Canvas对象的drawPath方法进绘制到页面上

# drawPath方法绘制path object
cav.drawPath(aPath=pathobject)

path object对象(PDFPathObject)的一些方法:

方法说明
moveTo移动 画笔 到坐标 x,y
lineTo从画笔坐标点到x,y坐标点画一条直线,画笔落点=x,y坐标
curveTo从当前画笔位置开始用三个控制点绘制贝塞尔曲线,画笔落点改变
arcTo从当前画笔位置开始绘制arc,画笔落点改变
close放下画笔

lineTo方法:

# pathobject.moveTo(x,y)
# 提起画笔 移动到坐标 x,y
pathobject.moveTo(x=100,y=100)
cav.drawCentredString(x=100,y=100,text="100 100")
# pathobject.lineTo(x,y)
# 从画笔坐标点到x,y坐标点画一条直线
pathobject.lineTo(x=100,y=200)
cav.drawCentredString(x=100,y=200,text="100 200")
# 放下画笔
pathobject.close()
# drawPath方法绘制path object
cav.drawPath(aPath=pathobject)


curveTo方法:

# pathobject.curveTo(x1, y1, x2, y2, x3, y3)
# curveTo方法从当前画笔位置开始
# 使用(x1,y1)、(x2,y2)和(x3,y3)作为其他三个控制点绘制贝塞尔曲线
# 画笔落在(x3,y3)的点上
pathobject.moveTo(x=200,y=100)       
cav.setStrokeColor(aColor="red")
cav.drawCentredString(x=200,y=90,text="200 100")
cav.drawString(x=400,y=195,text="400 200")
cav.drawCentredString(x=300,y=410,text="300 400")
cav.line(200,100, 400,200)
cav.line(400,200, 300,400)
cav.setStrokeColor(aColor="black")
pathobject.curveTo(200,100, 400,200, 300,400) 
# 放下画笔
pathobject.close()
# drawPath方法绘制path object
cav.drawPath(aPath=pathobject)

Canvas对象的其他方法

Canvas对象的其他方法:

方法说明
setAuthor设置文件属性作者
setTitle设置文件属性标题
setSubject设置文件属性主题
getPageNumber获取当前Canvas对象的页数
pageHasData查看Canvas对象是否需要保存
getAvailableFonts返回可用PostScript字体名称的列表
setPageTransition设置PDF演示的页面转换效果
bookmarkPage当前页面创建一个书签
addOutlineEntry设置书签大纲目录
showOutline设置打开PDF默认显示大纲目录
showFullScreen0全屏模式打开PDf
# canvas.setAuthor(author)
cav.setAuthor("AuthorName")
# canvas.setTitle(title)
cav.setTitle(title="标题")
# canvas.setSubject(subj)
cav.setSubject(subject="主题")
# canvas.getPageNumber() 获取当前PDF页数
print("PageNumber", cav.getPageNumber())
# canvas.pageHasData() 在showPage后调用它,查看是否需要保存
print("pageHasData", cav.pageHasData())
# canvas.getAvailableFonts() 返回可用PostScript字体名称的列表
print("getAvailableFonts", cav.getAvailableFonts())

# 设置PDF演示的页面转换效果
# canvas.setPageTransition(effectname=None, duration=1,
#                          direction=0, dimension='H', motion='I')
# 参数 :
# direction_arg = [0, 90, 180, 270]
# dimension_arg = ['H', 'V']
# motion_arg = ['I', 'O'](start at inside or outside)
# PageTransitionEffects = {
#         'Split': [direction_arg, motion_arg],
#         'Blinds': [dimension_arg],
#         'Box': [motion_arg],
#         'Wipe' : [direction_arg],
#         'Dissolve' : [],
#         'Glitter':[direction_arg]
#         }
cav.setPageTransition(effectname='Split', duration=1, direction=0, dimension='H', motion='I')

# canvas.bookmarkPage(name) 当前页面创建一个书签
cav.bookmarkPage(key="mark_key")

addOutlineEntry方法:

# canvas.addOutlineEntry(title, key, level=0, closed=None)
# 设置书签目录 title名称
# key对应的书签==bookmarkPage方法的key
# level目录级别 
# closed是否展开子目录 默认展开 closed=1  隐藏子目录
cav.addOutlineEntry(title="绘制字符串", key="draw_str", level=0, closed=None)
cav.addOutlineEntry(title="绘制直线", key="draw_line", level=0, closed=None)
cav.addOutlineEntry(title="绘制形状", key="draw_shape", level=0, closed=None)
cav.addOutlineEntry(title="绘制图片", key="draw_image", level=0, closed=None)
cav.addOutlineEntry(title="改变颜色", key="change_color", level=0, closed=None)
cav.addOutlineEntry(title="线条样式", key="set_line", level=0, closed=None)
cav.addOutlineEntry(title="几何变换", key="set_geometry", level=0, closed=None)
cav.addOutlineEntry(title="画布缩放", key="set_scale", level=1, closed=None)
cav.addOutlineEntry(title="画布旋转", key="set_rotate", level=1, closed=1)
cav.addOutlineEntry(title="下一级", key="set_skew", level=2, closed=None)
    
# canvas.showOutline() 设置默认显示大纲目录
cav.showOutline()
# cav.showFullScreen0()

以上就是对ReportLab库 pdfgen模块Canvas对象的学习
如果有什么不对的地方欢迎指正!

主要参考:ReportLab PDF Library User Guide

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/792050.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存