Dick Kniep
Dick Kniep

Reputation: 528

Convert html to pdf using pyqt5 without showing a screen

I am trying to render html to pdf using QtWebEngineWidgets using the following code.

import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
from tempfile import gettempdir
from pathlib import Path

def printhtmltopdf(html_in, callback):
    tfile =Path(gettempdir(), 'printhtmltopdf.html')
    with open(tfile, 'wb') as tempf:
        tempf.write(html_in)
    app = QtWidgets.QApplication(sys.argv)
    loader = QtWebEngineWidgets.QWebEngineView()
    loader.setZoomFactor(1)
    loader.page().pdfPrintingFinished.connect(
        lambda *args: print('finished:', args))
    loader.load(QtCore.QUrl().fromLocalFile(str(tfile)))

    def emit_pdf(finished):
        loader.page().printToPdf(callback)
        app.exit(0)

    loader.loadFinished.connect(emit_pdf)

    app.exec()

However the callback is never triggered. When I omit the app.exit(0) it works, but it will wait for user interaction which I do not want. In fact I would prefer to execute the routine without the eventloop at all.

Upvotes: 1

Views: 450

Answers (1)

eyllanesc
eyllanesc

Reputation: 243983

You have to use a QWebEnginePage, also it is not necessary to create temporary files but you can load the HTML directly:

from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets


def printhtmltopdf(html_in, pdf_filename):
    app = QtWidgets.QApplication([])
    page = QtWebEngineWidgets.QWebEnginePage()

    def handle_pdfPrintingFinished(*args):
        print("finished: ", args)
        app.quit()

    def handle_loadFinished(finished):
        page.printToPdf(pdf_filename)

    page.pdfPrintingFinished.connect(handle_pdfPrintingFinished)
    page.loadFinished.connect(handle_loadFinished)

    page.setZoomFactor(1)
    page.setHtml(html_in)

    app.exec()


printhtmltopdf(
    """<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>Hello!</title>
    </head>

    <body>
        <h1>Hello World!</h1>
        <p>This is a simple paragraph.</p>
    </body>

</html>""",
    "test.pdf",
)

Upvotes: 3

Related Questions