使用canvas绘制图像并使用SimpleDocTemplate
我正在 django 视图中使用 reportlab 编写 pdf,它们非常简单,包括页眉、内容和页脚。
我正在使用非常适合的 SimpleDocTemplate 来绘制内容中的表格,页脚和页眉是 drwan 使用的:
build([data], onFirstPage=drawPageFrame, onLaterPages=drawPageFrame).
我的问题是,如何像使用 Canvas.drawImage(...) 一样绘制图像?我需要一个“浮动”图像...位于我想要的文本上方,而使用 SimpleDocTemplate 我没有 Canvas 对象来执行此操作。
搜索我发现了这个:
鸭嘴兽布局使用 Flowables。打包者通常会设置 当每个 flowable 被包装、分割或分割时,属性 canv 到每个 flowable 上 围绕wrap、split 和draw 方法进行绘制。在这些方法里面 您可以使用 self 的 canv 属性访问画布。
这个可以怎么用呢?
嗯,还有更多要测试的东西:
flowables.Macro
flowables.CallerMacro
# -*- coding: utf-8 -*- from reportlab.lib.pagesizes import A4, landscape, portrait from reportlab.lib.styles import getSampleStyleSheet from reportlab.platypus import Table, Flowable, SimpleDocTemplate, Paragraph, Spacer, Image from reportlab.lib import randomtext from reportlab import platypus import os,random styles = getSampleStyleSheet() path = os.path.realpath(os.path.dirname(__file__)) def drawPageFrame(canvas, doc): canvas.saveState() canvas.drawImage(path+"/ujiPDF.jpg",50,50,57,57) canvas.restoreState() doc = SimpleDocTemplate("salida.pdf",pagesize=A4) elementos = [] com = 'canvas.drawImage("'+path+'/ujiPDF.jpg",100,100,57,57)' print com elementos.append(platypus.flowables.Macro('canvas.saveState()')) print platypus.flowables.Macro(com) elementos.append(platypus.flowables.Macro(com)) elementos.append(platypus.flowables.Macro('canvas.restoreState()')) para = Paragraph(randomtext.randomText(randomtext.PYTHON,20), styles["Normal"]) elementos.append(para) doc.build(elementos,onFirstPage=drawPageFrame, onLaterPages=drawPageFrame)
这是宏方法...干净退出,但没有第二个图像。
I'm writing pdfs with reportlab inside a django view, they are very simple, the header, the contents and the footer.
I'm using SimpleDocTemplate wich fits very well, to draw tables in the contents, the footer and the header are drwan using:
build([data], onFirstPage=drawPageFrame, onLaterPages=drawPageFrame).
My question is, How can I draw a image like using Canvas.drawImage(...)? I need a "floating" image... positioned over the text where I want, and with SimpleDocTemplate I don't have a Canvas object to do this.
Searching I have found this:
The platypus layout stuff uses flowables. Packers normally set the
attribute canv onto each flowable when it is being wrapped, split or
drawn ie around the wrap, split and draw methods. Inside those methods
you have access to the canvas using the canv attribute of self.
How can this be used?
Ummmm, more stuff to test:
flowables.Macro
flowables.CallerMacro
# -*- coding: utf-8 -*- from reportlab.lib.pagesizes import A4, landscape, portrait from reportlab.lib.styles import getSampleStyleSheet from reportlab.platypus import Table, Flowable, SimpleDocTemplate, Paragraph, Spacer, Image from reportlab.lib import randomtext from reportlab import platypus import os,random styles = getSampleStyleSheet() path = os.path.realpath(os.path.dirname(__file__)) def drawPageFrame(canvas, doc): canvas.saveState() canvas.drawImage(path+"/ujiPDF.jpg",50,50,57,57) canvas.restoreState() doc = SimpleDocTemplate("salida.pdf",pagesize=A4) elementos = [] com = 'canvas.drawImage("'+path+'/ujiPDF.jpg",100,100,57,57)' print com elementos.append(platypus.flowables.Macro('canvas.saveState()')) print platypus.flowables.Macro(com) elementos.append(platypus.flowables.Macro(com)) elementos.append(platypus.flowables.Macro('canvas.restoreState()')) para = Paragraph(randomtext.randomText(randomtext.PYTHON,20), styles["Normal"]) elementos.append(para) doc.build(elementos,onFirstPage=drawPageFrame, onLaterPages=drawPageFrame)
This is the Macro approach...clean exit but without the second image.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果我理解正确的话,您不需要对整个文档模板进行子类化,您只需要一个可以放入 SimpleDocTemplate 的可流动文件。您可以通过 Flowable 本身的一个非常简单的子类来实现这一点。
->特别是,由于人们经常询问如何将 matplotlib 对象放入 reportlab,我将展示如何使用 matplotlib 生成绘图,然后使用修改后的 flowable 将该绘图放入 SimpleDocTemplate 中(无需将文件保存到磁盘)。这个概念适用于任何文件或任何可以输入 cStringIO 的内容
->下面的代码确实允许您将图形放在文本上(将高度从负值更改为正值,以将其推到绘图所在部分顶部的假想线上方)
关键概念是每个 Flowable 本身也可以包含我们可以在其上绘图的画布。
您可以扩展这个最小的代码片段来完成您喜欢的任何事情,并且您可以向 Story 变量添加任意多的片段(这实际上只是一个可流动的列表)。神奇之处在于我们向文档生成器提供了一个 Flowable,它使用 Flowable 自己的画布来绘制图形。
编辑:我差点忘了,因为这使我们能够完全访问drawImage,我们还可以使该图片或绘图具有透明度,以便可以通过它看到其他东西。 drawImage 上的文档有详细信息。
You don't need to subclass the whole document template if I understand you right, you just want a flowable that you can put INTO a SimpleDocTemplate. You can achieve that with a very easy subclass of Flowable itself.
-> In particular since people often ask about how to put matplotlib objects into reportlab, I'll show how to generate a plot with matplotlib and then use the modified flowable to put that plot into a SimpleDocTemplate (without saving the file to disk). The concept applies to any file or anything you can feed into a cStringIO
-> The below DOES allow you to put the figure over the text (change the height from negative to positive to push it above the imaginary line at the top of the section the plot goes into)
The key concept is that each Flowable does, itself, also contain a canvas we can draw onto.
You can expand this minimum code snipped to accomplish whatever you like and you can add as many pieces to the Story variable (which is just a list of flowables really). The magic is just that we're handing the doc builder a Flowable that uses the Flowable's own canvas to draw the figure.
EDIT: I almost forgot, because this gives us full access to drawImage, we can also make that picture or plot have transparency so other things can be seen through it. The docs on drawImage have the details.
鸭嘴兽中有Image类。只需使用
from reportlab.platypus import Image
即可访问此类。它的工作方式与内部的其他类类似,并且smth.append(Image(filename))
将图像附加到您需要构建到 pdf 中的对象。创立于 Tyler Lessman 个人网站There is Image class in the platypus. Just use
from reportlab.platypus import Image
and you got access to this class. It works like other classes inside andsmth.append(Image(filename))
appends image to object you need to build into pdf. Founded at Tyler Lessman personal website最好的选择是创建 SimpleDocTemplate 或 BaseDocTemplate 的子类。在构建方法中,您将可以访问画布。如果您想利用 SimpleDocTemplate 所做的一切,您可以尝试直接从
site-packages/reportlab/platypus/doctemplate.py
复制它。Your best option is to create a subclass of SimpleDocTemplate or BaseDocTemplate. In the build method you will have access to the canvas. If you want to tap into everything that SimpleDocTemplate does, you might try copying it directly from
site-packages/reportlab/platypus/doctemplate.py
.