Reputation: 1734
I've tested at least 20 different workarounds for this.
I want to print a widget.
My widget is an Invoice and it have inside a lot of other widgets like QLineEdits, QLabels with text, QLabels that act as images, QDropDown menus, etc. This is a Screenshot (all data inside like the N.I.F are temporary placeholders for a real business):
So it should be easy, right? It does not seem so.
Code:
def print_as_pdf(widgettoprint):
# Printer
printer = QPrinter()
setupdialog = QPrintDialog(printer, widgettoprint)
if setupdialog.exec() == QPrintDialog.Accepted:
# Renderer
painter = QPainter(printer)
painter.begin(printer)
# Scale it
xscale = printer.pageRect().width() / widgettoprint.width()
yscale = printer.pageRect().height() / widgettoprint.height()
scale = min(xscale, yscale)
painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2,
printer.paperRect().y() + printer.pageRect().height() / 2)
painter.scale(scale, scale)
painter.translate(-1 * widgettoprint.width() / 2, -1 * widgettoprint.height() / 2)
widgettoprint.render(painter)
painter.end()
return True
else:
return False
It does the trick, it prints an entire A4 page as intended, but the quality of the texts is quite bad. I found out it just takes an screenshot of it instead of saving the data as text or vector data.
So that wouldn't work for me, but I had to try. I tried to print as PDF with the same method (choosing PDF as a printer) and it just generates a PDF with an screenshot on it. I can't select or copy the text data.
Code:
import os
from jinja2 import Environment, FileSystemLoader
from PyQt5 import QtWebEngineWidgets
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog
from PyQt5.QtGui import QPainter
PATH = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_ENVIRONMENT = Environment(
autoescape=False,
loader=FileSystemLoader(os.path.join(PATH, 'userfiles/templates')),
trim_blocks=False)
def render_template(template_filename, context):
return TEMPLATE_ENVIRONMENT.get_template(template_filename).render(context)
def test():
something = ['something1', 'something2', 'something3']
context = {
'something': something,
'invoicenumber': "17012"
}
# Generate the HTML data with the template without creating a file, on-the-fly
html = render_template('invoices.html', context)
# add html to a webengine/widget
web = QtWebEngineWidgets.QWebEngineView()
web.page().setHtml(html)
# Print that widget
printer = QPrinter()
setupdialog = QPrintDialog(printer)
if setupdialog.exec() == QPrintDialog.Accepted:
web.render(printer)
print("done")
test()
Where the HTML template is:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Factura {{ invoicenumber }}</title>
</head>
<body>
<center>
<h1>Factura {{ invoicenumber }}</h1>
<p>{{ something|length }} something</p>
</center>
<ol align="left">
{{ something[0] }}
{{ something[1] }}
{{ something[2] }}
</ol>
</body>
</html>
I will probably spend more weeks and months trying to make that works. Printing is something that I though it should had been really easy, as every random program in the market seems to be able to print or create PDFs, but it's now for me the worst part of my programming learning experience.
The goal: This question aims to find a permanent solution to my problem: how to print to a selectable (windows platform) printer my invoice widget? And then, if PDF printer is chosen, print it with endless quality, using vectors or anything that is just don't create an screenshot.
I'd also appreciate explanations of what I am doing wrong as I'm still learning (both programming, Python and Qt).
Upvotes: 2
Views: 3417
Reputation: 1576
Although I myself program in python, I have little knowledge about programming GUI in it. However, I found several questions and sites that can be a starting point to your own implementation. I know some of these are QT4 but please, have a look at them, I believe that things didn't change so much (but I can be wrong):
Pyqt take screenshot of certain screen area
Screenshot of a window using python
QT documentation Screenshot example
https://github.com/Python-Devs-Brasil/PyQt5-Tutorials/blob/master/Post-2(QtCore)/screenshot.py
https://github.com/baoboa/pyqt5/blob/master/examples/desktop/screenshot.py
How to grab a desktop screenshot with PyQt?
EDIT
Have you tried saving to a pdf file via matplotlib
?
https://pythonspot.com/en/matplotlib-save-figure-to-image-file/
saving images in python at a very high quality
EDIT 2
Also, have a look at this
Create a pdf with fillable fields python
EDIT 3
You can also have a look at documentations and examples of libraries mentioned in this question
Python PDF library
Upvotes: 1