Search code examples
qtpyqtretina-displayqgraphicsviewqgraphicsitem

QGraphicsItem rendering on Apple Retina Display


I'm adding support for the Apple Retina Display to my PyQt5 application. While I successfully managed to render high resolution icons (by adding the @2x suffix to all my .png files and setting the Qt.AA_UseHighDpiPixmaps in my QApplication), I'm having some troubles in rendering high resolutions QGraphicsItem in a QGraphicsScene + QGraphicsView.

In my application, other than loading .png files, I also generate several QPixmap my self (embedding them into a Icon), to build the palette of symbols the user can use to add new shapes to the diagram rendered in the QGraphicsView, i.e:

def icon(cls, width, height, **kwargs):
    """
    Returns an icon of this item suitable for the palette.
    :type width: int
    :type height: int
    :rtype: QIcon
    """
    icon = QIcon()
    for i in (1.0, 2.0):
        # CREATE THE PIXMAP
        pixmap = QPixmap(width * i, height * i)
        pixmap.setDevicePixelRatio(i)
        pixmap.fill(Qt.transparent)
        # PAINT THE SHAPE
        polygon = cls.createPolygon(46, 34)
        painter = QPainter(pixmap)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(QPen(QColor(0, 0, 0), 1.1, Qt.SolidLine))
        painter.setBrush(QColor(252, 252, 252))
        painter.translate(width / 2, height / 2)
        painter.drawPolygon(polygon)
        # PAINT THE TEXT INSIDE THE SHAPE
        painter.setFont(Font('Arial', 11, Font.Light))
        painter.drawText(polygon.boundingRect(), Qt.AlignCenter, 'role')
        painter.end()
        # ADD THE PIXMAP TO THE ICON
        icon.addPixmap(pixmap)
    return icon

Which generate one of the symbols in my Palette (the diamond one).

Eddy Palette

However when I add elements to my QGraphicsScene, displayed in a QGraphicsView they are rendered in low resolution:

def paint(self, painter, option, widget=None):
    """
    Paint the node in the diagram.
    :type painter: QPainter
    :type option: QStyleOptionGraphicsItem
    :type widget: QWidget
    """
    painter.setPen(self.pen)
    painter.setBrush(self.brush)
    painter.drawPolygon(self.polygon)

Eddy Diagram

The text within the shape is rendered correctly, and I'm not painting it myself since it's a QGraphicsTextItem having my QGraphicsItem as parent.

The problem is that while for QPixmap I can set the device pixel ratio, for QGraphicsItem i cannot. Am I missing something?

I'm using PyQt 5.5.1 built against Qt 5.5.1 and SIP 4.18 (not using 5.6 since I'm experiencing several crashes on application startup which I already reported to PyQt devs).


Solution

  • Probably not what you wanted to hear, but Qt added retina support in 5.6.