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?
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_())