使用 QPrinter 和 Jinja2 生成带有图像的 pdf



我一直在尝试生成一个包含图像但图像不显示的PDF。我遵循了本指南。

指南下方有一条评论说我应该使用app.processEvents()来包含其他资源。

我还发现loadFinished.connect在调用打印之前等待 html 加载,但我似乎无法使其工作。

这是我的代码:

class Window(QtGui.QMainWindow):
    ........
    btn1.clicked.connect(self.tohtml)
    def tohtml(self):
        # Random 2D list
        table = [[random.randint(0, 100) for j in range(10)] for i in range(10)]
        # Some Lorem Ipsum text
        paragraphs = [p[2] for p in generate_paragraphs(3)]
        self.html = render_template("test.html", table=table, paragraphs=paragraphs)
        self.topdf(self.html, "file.pdf")
    def topdf(self, html, destination):
        self.web = QWebView()
        self.web.setHtml(html)
        self.printer = QPrinter(QPrinterInfo.defaultPrinter(),QPrinter.HighResolution)
        self.printer.setPageSize(QPrinter.A4)
        self.printer.setOutputFormat(QPrinter.PdfFormat)
        self.printer.setOutputFileName(destination)  
        self.web.loadFinished.connect(self.print_pdf)
    def print_pdf (self):
        self.web.print_(self.printer)

这是我的测试html:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        .centered {
            text-align: center;
        }
        .underlined {
             text-decoration: underline;
        }
        .datatable {
            width: 100%;
            border-collapse: collapse;
        }
        .datatable td {
            margin: 0px;
            border: 1px solid #000;
            text-align: right;
    }
</style>
</head>
    <body>
         <img src="IDSLOGO.jpg"/>
    </body>
</html>

任何帮助或指导将不胜感激。

首先感谢 github 的 adewes,毕竟这是他的代码

这就是我所理解的,至少解决了我的问题(在code_byter的帮助下(

我的模板没有任何问题,原因是缺乏细节告诉QWebView我的照片在哪里,所以添加

url = QUrl.fromLocalFile(media_path)然后

web.setHtml(html,baseUrl = url)

现在QWebview为我看到了图像,并准备将其与jinja2中的html字符串一起渲染 最后,app.processEvents()循环遍历事件(渲染和获取资源(,等待 QWebview 或事件完成,然后再继续,因为 QWebView 立即返回,而无需等待所有内容渲染。

代码如下:

jinja_env  = Environment(loader=FileSystemLoader("templates"))
def generate_pdf(template, filename, media_path=None, template_context=None):
    global app
    if template_context is None:
        template_context = {}                   #this is a dictionary
    template_context['media_path'] = media_path 
    #adds your os.path.abspath('your_absolute_dir_to_images') to the context dict, in the examples's case it's media
    template_path = '{0}.html'.format(template) #adds .html extension to a string ('your_template_name' + '.html')
    template = jinja_env.get_template(template_path) #gets and loads the template (your_template_name.html)
    html = template.render(**template_context)       #this executes the {{}} and {%%} inside your template
    app = QApplication.instance()
    if app is None:                                  #prevents a crash
        app = QApplication(['--platform','minimal'])
    web = QWebView()                                  #next step after setting up the jinja part is passing the generated html to WebView
    url = QUrl.fromLocalFile(media_path)              #this stores a command telling webview that this is the dir where the picture is or resources
    web.setHtml(html,baseUrl = url)                   #sets your template or html to be read and the resource location
    app.processEvents()                               #this loops through the events in QApplication and waits for webview to be finished rendering the html
    printer = QPrinter()                              #after webview renders the html this part will now execute. It's pretty straightforward
    printer.setPageSize(QPrinter.A4)
    printer.setOutputFormat(QPrinter.PdfFormat)
    printer.setOutputFileName(filename)
    web.print_(printer)                               #now prints a pdf with image yay

您可能不需要这里的一些代码来将其集成到您自己的代码中,但我将使用它,因为您基本上可以复制和粘贴它并且它会起作用(如果您有依赖项(如果您发现这很有用,请不要忘记感谢 Adewes,如果有什么我理解不正确的地方,请随时编辑。

编辑: 忘了提到我的 html 标签看起来像这样<img src="{{media_path}}/my_pic.png" /> 它也可能看起来像这样<img src="file://{{media_path}}/my_pic.png" />但后者对我不起作用。

最新更新