mkeeter
mkeeter

Reputation: 73

Fully transparent mask -> fully opaque widget

I ran into a strange corner case when attempting to render a fully transparent widget in PySide.

If I call setMask with a QBitmap that is filled with Qt.color0, it makes the widget completely opaque (rather than completely transparent, as I would expect).

Putting in a single pixel of Qt.color leads to the expected behavior: the widget becomes completely transparent other than that single pixel.

Below is a minimal example. Changing the variable single_pixel to True fills in the top left pixel, which causes the mask to start working as expected.

Any ideas what's going on here?

import sys
from PySide import QtCore, QtGui

app = QtGui.QApplication(sys.argv)

widget = QtGui.QWidget()
widget.resize(200, 200)
widget.show()

bitmap = QtGui.QBitmap(widget.size())
bitmap.clear()

single_pixel = False
if single_pixel:
    painter = QtGui.QPainter()
    painter.begin(bitmap)
    painter.setPen(QtCore.Qt.color1)
    painter.drawPoint(0,0)
    painter.end()

widget.setMask(bitmap)

sys.exit(app.exec_())

Upvotes: 4

Views: 475

Answers (1)

Pavel Strakhov
Pavel Strakhov

Reputation: 40492

QWidget::setMask(QBitmap) converts QBitmap to QRegion and calls QWidget::setMask(QRegion). QRegion produced by empty bitmap is empty. So using empty bitmap in setMask is equal to widget.setMask(QRegion()). Qt assumes that providing empty region means unsetting mask. This is reasonable because there is no other validity flag in QRegion besides isEmpty. QWidget::mask returns empty region when no mask is set according to documentation, so empty QRegion is apparently treated as a special value meaning that no mask is set.

In QWidget::setMask(QRegion):

d->extra->mask = newMask;
d->extra->hasMask = !newMask.isEmpty();

This is probably a bug in Qt documentation. QWidget::setMask docs should contain a note about this.

Upvotes: 3

Related Questions