geekdoc-python-zh/docs/pythonlibrary/reportlab-101-the-textobjec...

9.6 KiB
Raw Permalink Blame History

ReportLab 101:文本对象

原文:https://www.blog.pythonlibrary.org/2018/02/06/reportlab-101-the-textobject/

ReportLab 工具包为您提供了多种在 pdf 上生成文本的方法。我见过的最流行的例子是使用画布方法或使用鸭嘴兽。你最有可能看到的画布方法是拉绳。这里有一个例子:


from reportlab.pdfgen import canvas

c = canvas.Canvas("hello.pdf")
c.drawString(100, 100, "Welcome to Reportlab!")
c.showPage()
c.save()

基本上就是在给定的 x/y 坐标上画一个字符串。使用鸭嘴兽要复杂得多:


from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph
from reportlab.lib.styles import getSampleStyleSheet

def hello():
    doc = SimpleDocTemplate("hello_platypus.pdf",
                            pagesize=letter,
                            rightMargin=72,
                            leftMargin=72,
                            topMargin=72,
                            bottomMargin=18)
    styles = getSampleStyleSheet()

    flowables = []

    text = "Hello, I'm a Paragraph"
    para = Paragraph(text, style=styles["Normal"])
    flowables.append(para)

    doc.build(flowables)

if __name__ == '__main__':
    hello()

你会注意到大多数时候当你使用鸭嘴兽的时候你会需要使用一个模板一个样式和一个段落或者其他可流动的东西。但是让我们回到画布上。它实际上有另一种生成文本的方法ReportLab 调用 textobject 。坦白地说,我从来不需要这些,因为 ReportLab 的段落类可以让你更好地控制文本的呈现。但是如果你依赖于使用低级画布来生成你的 PDF那么你会想知道 textobject 会使 PDF 生成更快,因为它不使用对拉绳的单独调用。


文本对象

以我的经验来看,学习新东西的最好方法就是试着写一些简单的演示。所以让我们写一些代码,看看 textobject 是如何工作的:


# textobject_demo.py

from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

def textobject_demo():
    my_canvas = canvas.Canvas("txt_obj.pdf",
                              pagesize=letter)
    # Create textobject
    textobject = my_canvas.beginText()

    # Set text location (x, y)
    textobject.setTextOrigin(10, 730)

    # Set font face and size
    textobject.setFont('Times-Roman', 12)

    # Write a line of text + carriage return
    textobject.textLine(text='Python rocks!')

    # Change text color
    textobject.setFillColor(colors.red)

    # Write red text
    textobject.textLine(text='Python rocks in red!')

    # Write text to the canvas
    my_canvas.drawText(textobject)

    my_canvas.save()

if __name__ == '__main__':
    textobject_demo()

这里我们了解到,要创建一个 textobject ,我们需要调用画布的 beginText 方法。如果你碰巧打印出了 textobject你会发现它在技术上是reportlab . pdf gen . textobject . pdftextobject的一个实例。无论如何,现在我们有了一个 textobject我们可以通过调用 setTextOrigin 来设置它的光标位置。然后我们像之前看到的那样设置字体和大小。下一个新项目是对 textLine 的调用,这将允许您向缓冲区写入一个字符串,外加一个基本上是回车的内容。该方法的 docstring 声明它使“文本光标下移”,但在我看来这相当于回车。还有一个 textLines 方法,允许您写出多行字符串。

接下来我们要做的是通过调用 setFillColor 来设置字体颜色。在本例中,我们将下一个文本字符串设置为红色。最后一步是调用 drawText ,它将实际绘制你的 textobject 中的任何内容。如果你跳过调用 drawText ,那么你的文本将不会被写出,你可能会得到一个空的 PDF 文档。

从 textobject 中可以调用许多其他方法。例如,如果你想移动光标的位置,而不是下一行,你可以调用 moveCursor 。让我们来看看:


from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

def textobject_cursor():
    canvas_obj = canvas.Canvas("textobj_cursor.pdf", pagesize=letter)

    # Create textobject
    textobject = canvas_obj.beginText()

    # Set text location (x, y)
    textobject.setTextOrigin(10, 730)

    for indent in range(4):
        textobject.textLine('ReportLab cursor demo')
        textobject.moveCursor(15, 15)

    canvas_obj.drawText(textobject)
    canvas_obj.save()

if __name__ == '__main__':
    textobject_cursor()

在这里,我们只是建立了一个循环,它将打印出相同的字符串四次,但是在四个不同的位置。您会注意到,在循环的每次迭代中,我们将光标向右移动 15 点,向下移动 15 点。是的,当使用一个文本对象时,一个正的 y 数将使你向下移动。

现在,假设你想改变字符间距;你需要做的就是调用 setCharSpace 。事实上,你可以用 textobject 做很多有趣的间距技巧,比如使用 setWordSpace 改变 word 之间的间距,或者通过调用 setLeading 改变行与行之间的间距。让我们来看看如何改变文本的间距:


from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

def textobject_char_spacing():
    canvas_obj = canvas.Canvas("textobj_char_spacing.pdf",
                               pagesize=letter)

    # Create textobject
    textobject = canvas_obj.beginText()

    # Set text location (x, y)
    textobject.setTextOrigin(10, 730)

    spacing = 0
    for indent in range(8):
        textobject.setCharSpace(spacing)
        line = '{} - ReportLab spacing demo'.format(spacing)
        textobject.textLine(line)
        spacing += 0.7

    canvas_obj.drawText(textobject)
    canvas_obj.save()

if __name__ == '__main__':
    textobject_char_spacing()

在本例中,我们将循环因子增加到 8 次迭代,并在每次循环中调用 setCharSpace() 。我们从零间距开始,然后在每次迭代中增加 0.7。您可以在这里看到结果:

现在让我们看看应用单词间距如何影响我们的文本:


from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

def wordspacer():
    canvas_obj = canvas.Canvas("textobj_word_spacing.pdf",
                               pagesize=letter)

    # Create textobject
    textobject = canvas_obj.beginText()

    # Set text location (x, y)
    textobject.setTextOrigin(10, 730)

    word_spacing = 0
    for indent in range(8):
        textobject.setWordSpace(word_spacing)
        line = '{} - ReportLab spacing demo'.format(word_spacing)
        textobject.textLine(line)
        word_spacing += 1.5

    canvas_obj.drawText(textobject)
    canvas_obj.save()

if __name__ == '__main__':      
    wordspacer()

这个例子与前一个非常相似,但是你会注意到我们调用的是 setWordSpace() 而不是 setCharSpace() ,在这个例子中我们将间距增加了 1.5 倍。生成的文本如下所示:

如果你想创建一个上标或下标,那么你需要在你的文本对象上调用setRise。让我们创建一个演示,演示如何在 ReportLab 中设置上升:


from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

def apply_scripting(textobject, text, rise):
    textobject.setFont("Helvetica-Oblique", 8)
    textobject.setRise(rise)
    textobject.textOut(text)
    textobject.setFont("Helvetica-Oblique", 12)
    textobject.setRise(0)

def main():
    canvas_obj = canvas.Canvas("textobj_rising.pdf",
                               pagesize=letter)

    # Create textobject
    textobject = canvas_obj.beginText()
    textobject.setFont("Helvetica-Oblique", 12)

    # Set text location (x, y)
    textobject.setTextOrigin(10, 730)

    textobject.textOut('ReportLab ')
    apply_scripting(textobject, 'superscript ', 7)

    textobject.textOut('and ')

    apply_scripting(textobject, 'subscript ', -7)

    canvas_obj.drawText(textobject)
    canvas_obj.save()

if __name__ == '__main__':
    main()

这里我们创建了几个函数, apply_scriptingmain 。主函数将创建我们的画布和我们需要的所有其他部分。然后我们写出一些普通的文本。接下来的几行是我们应用上标(正)和下标(负)的地方。注意我们需要将上标和下标之间的升程设置回零以使单词“and”出现在正确的位置。一旦应用了一个上升的值它将从该点开始继续应用。因此您需要将它重置为零以确保文本保持在正常位置。您还会注意到我们将上标和下标的字体大小设置为小于常规文本。以下是运行此示例的结果:

查看 ReportLab 的用户指南,了解您可以做的更多有趣的事情,或者查看源代码本身。


包扎

我们在本教程中介绍了很多信息,但是您现在应该对如何在画布上使用 ReportLab 的 textobject 有了很好的理解。它非常有用,可以让你的文本格式变得非常简单。另一个很大的好处是它比多次调用 drawText() 要快。有机会一定要试一试!

注意:本教程是基于我最近的一本书的一部分, ReportLab:用 Python 处理 PDF


相关阅读