The mask is always based in widget coordinates, but if you change the alignment of the image it won't translate the mask along with it.
A possible solution is to install an event filter on the label and update the mask whenever it's resized. In order to do so, we need to keep a persistent reference of the mask, but using a QRegion (which allows translation):
self.baseMask = QRegion(self.pix.createMaskFromColor(Qt.transparent, Qt.MaskOutColor))
self.picture.setMask(self.baseMask)
self.picture.installEventFilter(self)
# ...
def eventFilter(self, obj, event):
if event.type() == QEvent.Type.Resize:
rect = self.picture.pixmap().rect()
rect.moveCenter(self.picture.rect().center())
self.picture.setMask(self.baseMask.translated(rect.topLeft()))
return super().eventFilter(obj, event)
Alternatively, with a subclass:
class MaskLabel(QLabel):
baseMask = None
def setMask(self, mask):
if isinstance(mask, QBitmap):
mask = QRegion(mask)
self.baseMask = mask
self.updateMask()
def updateMask(self):
if self.baseMask and self.pixmap():
rect = self.pixmap().rect()
rect.moveCenter(self.rect().center())
super().setMask(self.baseMask.translated(rect.topLeft()))
def resizeEvent(self, event):
self.updateMask()
Obviously, the above is only valid for centered images, if you need a different alignment, you need to verify the alignment direction and eventually translate the mask accordingly, based on the label rect()
.