How to scale a QPixmap preserving aspect and centering the image?

898 views Asked by At

I want to use an image (svg file) as background in an QMdiArea. I load the image as QPixmap and scale it in the resizeEvent method to the size of the QMdiArea using

self._background_scaled = self._background.scaled(self.size(), QtCore.Qt.KeepAspectRatio)
self.setBackground(self._background_scaled)

But that puts the image in the upper left corner and repeats it in either X or Y. I want the image to be centered.

How do I scale the QPixmap so it is resized preserving aspect ratio but then add borders to get the exact size?

1

There are 1 answers

0
eyllanesc On BEST ANSWER

The setBackground() method accepts a QBrush that is built based on the QPixmap you pass to it, but if a QBrush is built based on a QPixmap it will create the texture (repeating elements) and there is no way to change that behavior. So the solution is to override the paintEvent method and directly paint the QPixmap:

import sys

from PySide2 import QtCore, QtGui, QtWidgets


def create_pixmap(size):
    pixmap = QtGui.QPixmap(size)
    pixmap.fill(QtCore.Qt.red)
    painter = QtGui.QPainter(pixmap)
    painter.setBrush(QtCore.Qt.blue)
    painter.drawEllipse(pixmap.rect())
    return pixmap


class MdiArea(QtWidgets.QMdiArea):
    def __init__(self, parent=None):
        super().__init__(parent)
        pixmap = QtGui.QPixmap(100, 100)
        pixmap.fill(QtGui.QColor("transparent"))
        self._background = pixmap

    @property
    def background(self):
        return self._background

    @background.setter
    def background(self, background):
        self._background = background
        self.update()

    def paintEvent(self, event):
        super().paintEvent(event)
        painter = QtGui.QPainter(self.viewport())
        background_scaled = self.background.scaled(
            self.size(), QtCore.Qt.KeepAspectRatio
        )
        background_scaled_rect = background_scaled.rect()
        background_scaled_rect.moveCenter(self.rect().center())
        painter.drawPixmap(background_scaled_rect.topLeft(), background_scaled)


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)

    mdiarea = MdiArea()
    mdiarea.show()

    mdiarea.background = create_pixmap(QtCore.QSize(100, 100))

    sys.exit(app.exec_())