0

I am using PyQt 5.15.2 (Qt 5.15.2) on macOs 10.15.7. I am trying to produce a PDF from a QGraphicsScene. I am drawing some paths with a brush that has a pixmap texture, and a scale transformation applied (with brush.setTransform). When I display the scene in a QGraphicsView I get exactly the desired output. When I render the same scene to a QPrinter (set to produce a pdf) the texture is applied but ignoring the transformation. Is this a known limitation? Is there a way around it?

Below is a minimal example showing the problem in a context similar to my use case. Here I am creating a texture on the fly for illustration purposes. The rendering artifacts due to antialiasing are irrelevant for my question. The issue is the discrepancy between the scale (set at .5) of the texture in the rendered brush and the scale (always 1) in the pdf output. [To generate the output just double click on the view, you'll see a test.pdf in the current path.]

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtPrintSupport import *

class Test(QGraphicsView):

  def __init__(self):
    QGraphicsView.__init__(self)

    # Here I am creating a texture for testing
    # it is a 50x50 black square
    s = 50
    img = QImage(s, s, QImage.Format_ARGB32)
    img.fill(Qt.transparent)
    for x in range(s):
      img.setPixelColor(x,0,Qt.black)
      img.setPixelColor(x,s-1,Qt.black)
      img.setPixelColor(s-1,x,Qt.black)
      img.setPixelColor(0,x,Qt.black)

    self.scene = QGraphicsScene()
    self.setScene(self.scene)
    r = self.scene.addRect(0, 0, 1404, 1872)

    pen = QPen()
    pen.setWidth(150)
    pen.setCapStyle(Qt.RoundCap)
    pen.setJoinStyle(Qt.RoundJoin)

    b=QBrush(img)
    # Here I am transforming the brush so that the texture should be scaled 50% in both height and width
    tr = QTransform()
    tr.scale(.5,.5)
    b.setTransform(tr)
    pen.setBrush(b)

    # A random path for testing, drawn using the textured brush
    path = QPainterPath(QPointF(200, 200))
    path.lineTo(300,300)
    path.lineTo(300,1000)
    path.lineTo(700,700)
    self.pathItem = QGraphicsPathItem(path, r)
    self.pathItem.setPen(pen)

  def resizeEvent(self, event):
    self.fitInView(self.sceneRect(), Qt.KeepAspectRatio)

  def mouseDoubleClickEvent(self, event):
    printer = QPrinter(QPrinter.HighResolution)
    printer.setOutputFormat(QPrinter.PdfFormat)
    # printer.setPageSize(QPrinter.A4)
    printer.setOutputFileName("test.pdf")
    printer.setPaperSize(QSizeF(1404,1872), QPrinter.Millimeter)
    printer.setPageMargins(0,0,0,0, QPrinter.Millimeter)
    p=QPainter()
    p.begin(printer)
    self.scene.render(p)
    p.end()

if __name__ == '__main__':
  app = QApplication([])
  print(QT_VERSION_STR)
  print(PYQT_VERSION_STR)
  viewer = Test()
  viewer.show()
  app.exec_()

The desired output is on the left, as correctly displayed by the QGraphicsView. On the right is the PDF rendering of the same scene, which incorrectly ignores the scaling of the brush.

preview

Bordaigorl
  • 121
  • 6
  • With your given code it's a bit difficult to understand what's the *actual* expected result (I don't completely understand your texture and the relation with coordinates). Can you provide a result on your platform and the expected result for the pdf (or, at least, an approximation)? – musicamante May 09 '21 at 11:36
  • @musicamante I added a preview showing the issue. The `QGraphicsView` correctly paints the path using a brush with the texture scaled down 50%. The same scene rendered to a PDF ignores the scale on the brush. – Bordaigorl May 10 '21 at 08:29

0 Answers0