barkowski@shinobi-mail.de
19th January 2019, 15:52
Hey there!
I have a problem with PyQt5 and QPrinter which seems to be related to PyQt 5.11.3 or Qt 5.12. I’m running Manjaro Linux (Kenel 4.20) with python 3.7.2, pyqt5-common 5.11.3, python-pyqt5 5.11.3 and Qt5 at v5.12.0.
(The problem occurs also in openSuse Tumbleweed. It seems, that it is not specific to Manjaro or Arch Linux)
I have a program which printed directly to a pdf-file in portrait- or landscape-orientation using QPrinter. Everything worked perfectly with PyQt5 v5.11.2 and Qt5 v5.11.2.
But now after update to Qt5.12 and pyqt5.11.3, whitout any code-changes, I always get documents in format "us-letter" in portrait-orientation.
I have a minimal working-example and some pdf-files to illustrate this here: https://www.dropbox.com/sh/feve6ubvylrko0x/AACC8W0hqEQWSu3t5zGdQI9ra?dl=0
(I had to remove names in two of the documents with LibreOffice Draw. Thus, the specs say that they are generated by LibreOffice instead of Qt5.12.)
In my example script, I let python print the printer-settings and they are correct, but the generated output is wrong.
Can anybody confirm and reproduce this behaviour with my working example?
Thank you!
Regards,
Sam Barkowski
Here is a working example in a Code-Tag:
from decimal import Decimal
import os
import sys
import platform
import tempfile
from PyQt5.QtWidgets import QWidget, QToolTip, QPushButton, QApplication
from PyQt5.QtGui import QPainter, QFont, QDesktopServices, QPen, QColor, QTextOption, QPageLayout, QPageSize
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog
from PyQt5.QtCore import Qt, QUrl, QRectF, QMarginsF, QSizeF
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.printer = QPrinter(300) # QPrinter.HighResolution
self.printer.setPageSize(QPrinter.A4)
self.printer.setOutputFormat(QPrinter.PdfFormat)
print("Printercheck1:", self.printer.isValid())
self.tempdir = tempfile.mkdtemp(prefix="PyTesting-")
self._Windows = False
if platform.system() == "Windows":
self._Windows = True
def initUI(self):
QToolTip.setFont(QFont('SansSerif', 10))
self.setToolTip('Try printing')
btn = QPushButton('Print portrait-pdf', self)
btn.setToolTip('This should produce a PDF in portrait mode in A4 format')
btn.resize(btn.sizeHint())
btn.move(60, 50)
btn.clicked.connect(lambda:self.exPrint(pdf=True, lscp=False))
btn2 = QPushButton('Print landscape-pdf', self)
btn2.setToolTip('This should produce a PDF in landscape mode in A4 format')
btn2.resize(btn.sizeHint())
btn2.move(60, 100)
btn2.clicked.connect(lambda:self.exPrint(pdf=True, lscp=True))
btn3 = QPushButton('Print dialog portrait', self)
btn3.setToolTip('Open Print-Dialog portrait')
btn3.resize(btn.sizeHint())
btn3.move(60, 150)
btn3.clicked.connect(lambda:self.exPrint(pdf=False , lscp=False))
btn4 = QPushButton('Print dialog lscp', self)
btn4.setToolTip('Open Print-Dialog landscape')
btn4.resize(btn.sizeHint())
btn4.move(60, 200)
btn4.clicked.connect(lambda:self.exPrint(pdf=False , lscp=True))
self.setGeometry(400, 400, 400, 300)
self.setWindowTitle('Printing-Test')
self.show()
def printsettings(self, pdf=True, name="", landscp=False):
printservice = None
painter = None
filename = None
if pdf or self._Windows:
printservice = self.printer
if landscp:
try:
printservice.setPageOrientation(QPageLayout.Landsc ape)
print("Printercheck2:", printservice.isValid())
except Exception as e:
print("Exception in printersettings:", e.args[0])
else:
try:
printservice.setPageOrientation(QPageLayout.Portra it)
except Exception as e:
print("Exception in printersettings::", e.args[0])
print("Current settings:", printservice.pageLayout().pageSize().size(QPageSiz e.Millimeter), printservice.pageLayout().orientation())
if self._Windows:
slash = "\\"
else:
slash = "/"
filename = self.tempdir + slash + name + ".pdf"
self.printer.setOutputFileName(filename)
self.printer.setDocName(filename)
else:
filename = ""
printservice = QPrinter(300) # 300 QPrinter.HighResolution
printservice.setFullPage(True)
printservice.setPageSize(QPrinter.A4)
if landscp:
try:
printservice.setPageOrientation(QPageLayout.Landsc ape)
except Exception as e:
print("Exception in printersettings:", e.args[0])
else:
try:
printservice.setPageOrientation(QPageLayout.Portra it)
except Exception as e:
print("Exception in printersettings:", e.args[0])
dialog = QPrintDialog(printservice, None)
if not dialog.exec_():
return (None, None, None)
if printservice is not None:
painter = QPainter(printservice)
painter.setRenderHints(QPainter.TextAntialiasing)
painter.resetTransform()
scale = Decimal(1)
painter.scale(scale, scale)
return (printservice, painter, filename)
def finishjob(self, painter, filename, pdf=True):
painter.end()
if pdf:
url = QUrl.fromLocalFile(filename)
QDesktopServices.openUrl(url)
else:
if self._Windows:
try:
os.startfile(filename, "print")
except Exception as e:
print("Exception in attempt to print file:", filename, "ErrorMessage:", e.args[0])
def mm2pt(self, x):
"""used to calculate millimeters to point, for passing lengths in millimeter to the painter"""
if type(x) == float or type(x) == int:
return int(round(Decimal("360")/Decimal("127")*Decimal(x)))
else:
return None
def fromLeft(self, x):
"""distance from left paper edge in millimeters"""
return (self.mm2pt(x) - 18)
def fromTop(self, y):
"""distance from top edge of paper in millimeters"""
return (self.mm2pt(y) - 8)
def exPrint(self, pdf=True, lscp=False):
name = 'printingexample'
printmode = self.printsettings(pdf, name, lscp)
printservice = printmode[0]
painter = printmode[1]
filename = printmode[2]
if printservice is not None:
pen = QPen(QColor(0, 0, 0))
pen.setWidthF(0.4)
painter.setPen(pen)
sansFont = QFont("Sans Serif", 9, weight=45)
painter.setFont(sansFont)
x1 = self.fromLeft(17)
x2 = x1 + self.mm2pt(200)
t_left = QTextOption()
t_left.setAlignment(Qt.AlignLeft)
t_right = QTextOption()
t_right.setAlignment(Qt.AlignRight)
height = 12
rect = QRectF(x1, self.mm2pt(10), x2 - x1, 2*height)
painter.drawText(rect, "top left", t_left)
painter.drawText(rect, "top right", t_right)
try:
self.finishjob(painter, filename, pdf)
except (PermissionError, ProcessLookupError, FileExistsError, FileNotFoundError,
AttributeError, AssertionError, NotADirectoryError) as e:
print("Failed to open or print document. ErrorMessage:", e.args[0])
else:
print("Printservice not available.")
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
I have a problem with PyQt5 and QPrinter which seems to be related to PyQt 5.11.3 or Qt 5.12. I’m running Manjaro Linux (Kenel 4.20) with python 3.7.2, pyqt5-common 5.11.3, python-pyqt5 5.11.3 and Qt5 at v5.12.0.
(The problem occurs also in openSuse Tumbleweed. It seems, that it is not specific to Manjaro or Arch Linux)
I have a program which printed directly to a pdf-file in portrait- or landscape-orientation using QPrinter. Everything worked perfectly with PyQt5 v5.11.2 and Qt5 v5.11.2.
But now after update to Qt5.12 and pyqt5.11.3, whitout any code-changes, I always get documents in format "us-letter" in portrait-orientation.
I have a minimal working-example and some pdf-files to illustrate this here: https://www.dropbox.com/sh/feve6ubvylrko0x/AACC8W0hqEQWSu3t5zGdQI9ra?dl=0
(I had to remove names in two of the documents with LibreOffice Draw. Thus, the specs say that they are generated by LibreOffice instead of Qt5.12.)
In my example script, I let python print the printer-settings and they are correct, but the generated output is wrong.
Can anybody confirm and reproduce this behaviour with my working example?
Thank you!
Regards,
Sam Barkowski
Here is a working example in a Code-Tag:
from decimal import Decimal
import os
import sys
import platform
import tempfile
from PyQt5.QtWidgets import QWidget, QToolTip, QPushButton, QApplication
from PyQt5.QtGui import QPainter, QFont, QDesktopServices, QPen, QColor, QTextOption, QPageLayout, QPageSize
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog
from PyQt5.QtCore import Qt, QUrl, QRectF, QMarginsF, QSizeF
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.printer = QPrinter(300) # QPrinter.HighResolution
self.printer.setPageSize(QPrinter.A4)
self.printer.setOutputFormat(QPrinter.PdfFormat)
print("Printercheck1:", self.printer.isValid())
self.tempdir = tempfile.mkdtemp(prefix="PyTesting-")
self._Windows = False
if platform.system() == "Windows":
self._Windows = True
def initUI(self):
QToolTip.setFont(QFont('SansSerif', 10))
self.setToolTip('Try printing')
btn = QPushButton('Print portrait-pdf', self)
btn.setToolTip('This should produce a PDF in portrait mode in A4 format')
btn.resize(btn.sizeHint())
btn.move(60, 50)
btn.clicked.connect(lambda:self.exPrint(pdf=True, lscp=False))
btn2 = QPushButton('Print landscape-pdf', self)
btn2.setToolTip('This should produce a PDF in landscape mode in A4 format')
btn2.resize(btn.sizeHint())
btn2.move(60, 100)
btn2.clicked.connect(lambda:self.exPrint(pdf=True, lscp=True))
btn3 = QPushButton('Print dialog portrait', self)
btn3.setToolTip('Open Print-Dialog portrait')
btn3.resize(btn.sizeHint())
btn3.move(60, 150)
btn3.clicked.connect(lambda:self.exPrint(pdf=False , lscp=False))
btn4 = QPushButton('Print dialog lscp', self)
btn4.setToolTip('Open Print-Dialog landscape')
btn4.resize(btn.sizeHint())
btn4.move(60, 200)
btn4.clicked.connect(lambda:self.exPrint(pdf=False , lscp=True))
self.setGeometry(400, 400, 400, 300)
self.setWindowTitle('Printing-Test')
self.show()
def printsettings(self, pdf=True, name="", landscp=False):
printservice = None
painter = None
filename = None
if pdf or self._Windows:
printservice = self.printer
if landscp:
try:
printservice.setPageOrientation(QPageLayout.Landsc ape)
print("Printercheck2:", printservice.isValid())
except Exception as e:
print("Exception in printersettings:", e.args[0])
else:
try:
printservice.setPageOrientation(QPageLayout.Portra it)
except Exception as e:
print("Exception in printersettings::", e.args[0])
print("Current settings:", printservice.pageLayout().pageSize().size(QPageSiz e.Millimeter), printservice.pageLayout().orientation())
if self._Windows:
slash = "\\"
else:
slash = "/"
filename = self.tempdir + slash + name + ".pdf"
self.printer.setOutputFileName(filename)
self.printer.setDocName(filename)
else:
filename = ""
printservice = QPrinter(300) # 300 QPrinter.HighResolution
printservice.setFullPage(True)
printservice.setPageSize(QPrinter.A4)
if landscp:
try:
printservice.setPageOrientation(QPageLayout.Landsc ape)
except Exception as e:
print("Exception in printersettings:", e.args[0])
else:
try:
printservice.setPageOrientation(QPageLayout.Portra it)
except Exception as e:
print("Exception in printersettings:", e.args[0])
dialog = QPrintDialog(printservice, None)
if not dialog.exec_():
return (None, None, None)
if printservice is not None:
painter = QPainter(printservice)
painter.setRenderHints(QPainter.TextAntialiasing)
painter.resetTransform()
scale = Decimal(1)
painter.scale(scale, scale)
return (printservice, painter, filename)
def finishjob(self, painter, filename, pdf=True):
painter.end()
if pdf:
url = QUrl.fromLocalFile(filename)
QDesktopServices.openUrl(url)
else:
if self._Windows:
try:
os.startfile(filename, "print")
except Exception as e:
print("Exception in attempt to print file:", filename, "ErrorMessage:", e.args[0])
def mm2pt(self, x):
"""used to calculate millimeters to point, for passing lengths in millimeter to the painter"""
if type(x) == float or type(x) == int:
return int(round(Decimal("360")/Decimal("127")*Decimal(x)))
else:
return None
def fromLeft(self, x):
"""distance from left paper edge in millimeters"""
return (self.mm2pt(x) - 18)
def fromTop(self, y):
"""distance from top edge of paper in millimeters"""
return (self.mm2pt(y) - 8)
def exPrint(self, pdf=True, lscp=False):
name = 'printingexample'
printmode = self.printsettings(pdf, name, lscp)
printservice = printmode[0]
painter = printmode[1]
filename = printmode[2]
if printservice is not None:
pen = QPen(QColor(0, 0, 0))
pen.setWidthF(0.4)
painter.setPen(pen)
sansFont = QFont("Sans Serif", 9, weight=45)
painter.setFont(sansFont)
x1 = self.fromLeft(17)
x2 = x1 + self.mm2pt(200)
t_left = QTextOption()
t_left.setAlignment(Qt.AlignLeft)
t_right = QTextOption()
t_right.setAlignment(Qt.AlignRight)
height = 12
rect = QRectF(x1, self.mm2pt(10), x2 - x1, 2*height)
painter.drawText(rect, "top left", t_left)
painter.drawText(rect, "top right", t_right)
try:
self.finishjob(painter, filename, pdf)
except (PermissionError, ProcessLookupError, FileExistsError, FileNotFoundError,
AttributeError, AssertionError, NotADirectoryError) as e:
print("Failed to open or print document. ErrorMessage:", e.args[0])
else:
print("Printservice not available.")
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == "__main__":
main()