PDA

View Full Version : transparency, setMask, createHeuristicMask, createMaskFromColor, QPixmap



TheKedge
5th February 2007, 18:02
Hi all,
I know there's a lot of stuff on transparency, but I haven't quite found what I'm looking for.

I've a QLabel. I'd like the baskground to be transparent - that is, it should appear as text 'on the desktop'

this is what I'm doing:


LabelBase(QWidget *parent): QLabel(parent)
{
QPalette p(palette());//get the widget's default palette
p.setColor ( QPalette::WindowText, Qt::darkGreen );
setPalette(p);
}
void LabelBase::update (const QString text)
{
setText(text);
QWidget::setFixedSize(QLabel::sizeHint());

QPixmap pixmap = QPixmap::grabWidget ( this );
setPixmap(pixmap);
theMask = pixmap.createHeuristicMask(false);
//theMask = createMaskFromColor(Qt::darkGreen);
setMask(theMask);
}
(theMask, above, is a QRegion)
The problem that I can't seem to make a good mask from the text. createHeuristicMask() leaves unmasked 'holes' in the text (the character 'o' is filled, for instance), and createMaskFromColor() doesn't seem to do anything for me. examples are attached.

So, the question, how can I best make a mask for my text.

thanks
K

wysota
6th February 2007, 13:48
You can make a transparent pixmap, draw the text on it and then mask all pixels which are transparent by transforming that pixmap to a bitmap and applying the mask. Heuristic mask is not needed here.

TheKedge
6th February 2007, 17:21
Ok, sounds good, but , I'm sorry but all I can manage is to make a transparent pixmap of the right size!:confused:


func(QString text)
{
QPixmap pixmap(QPixmap::grabWidget ( this ));//just to get the right size
pixmap.fill ( Qt::transparent );//ok, now I have a transparent pixmap

//draw text onto the pixmap ??? how??

QBitmap bmp(QBitmap::fromImage(pixmap.toImage()));//is this the only way from QPixmap to QBitmap?

QBitmap mask(pixmap.mask());//what mask will this give me??
label->setMask(theMask);
}


sorry, I'm a little confused

oh, one more question: why won't pixmap.createMaskFromColor() work?

thanks, for your help
K

jpn
6th February 2007, 18:31
Try this:


#include <QtGui>

class MaskedLabel : public QLabel
{
protected:
void resizeEvent(QResizeEvent* event)
{
QLabel::resizeEvent(event);

QPixmap pixmap(size());
pixmap.fill(Qt::transparent);
QPainter::setRedirected(this, &pixmap);
QPaintEvent pe(rect());
paintEvent(&pe);
QPainter::restoreRedirected(this);
setMask(pixmap.mask());
}
};

int main(int argc, char* argv[])
{
QApplication a(argc, argv);
QLabel* label = new MaskedLabel();
label->setText("Qt Centre!");
QFont font = label->font();
font.setPointSize(72);
label->setFont(font);
label->show();
return a.exec();
}

Bitto
6th February 2007, 20:07
I think you're looking for something like an "overlay widget", that is, an invisible surface/layer that you can draw onto, which composes its content straight onto the desktop.

Afaik , Qt doesn't support this on any platform but Qtopia Core, but there are several approaches to "hacking" your way around it. The most common approach is to grab the desktop widget, and draw its contents onto your widget's background. Some people combine this with the Qt::WA_NoSystemBackground flag, which prevents the window system from auto-filling the widget background for every paint event (i.e., you're drawing onto what was there before). It's not a perfect solution by far, but it's what many do today.

Using masks doesn't really give you a good result; it both looks bad (mal-aliasing edges), and the performance of a complex mask can be... pretty discouraging.

You and all other Qt developers are waiting for the day that all platforms can support fast top-level alpha composition... When that day comes, Qt is likely to support what you want with a nice easy-to-use interface.

Disclaimer: This isn't my strongest field.

TheKedge
6th February 2007, 20:48
Thanks, jpn, that's exactly it. That's what I need. (see the attachment). Bitto is right about the masks not quit working neatly, but it's what I need right now.
fantastic.
thanks,

why does
QBitmap QPixmap::createMaskFromColor ( const QColor & maskColor )
not work - or do I misunderstand what it's supposed to do?

K

wysota
6th February 2007, 23:15
why does
QBitmap QPixmap::createMaskFromColor ( const QColor & maskColor )
not work - or do I misunderstand what it's supposed to do?


Antialiasing and palette optimisations may be breaking it.

haldrik
17th August 2007, 06:19
The most common approach is to grab the desktop widget, and draw its contents onto your widget's background. Some people combine this with the Qt::WA_NoSystemBackground flag, which prevents the window system from auto-filling the widget background for every paint event (i.e., you're drawing onto what was there before). It's not a perfect solution by far, but it's what many do today.

Hi Bitto, how can I get this approach?
Could you please show me a little example?

marcel
17th August 2007, 09:19
It has already been done on Windows.

Go and download the sources from this thread :http://www.qtcentre.org/forum/f-qt-programming-2/t-argb-windows-on-windows-8395.html/?highlight=argb

regards

luckychap
18th July 2011, 13:39
Try this:


#include <QtGui>

class MaskedLabel : public QLabel
{
protected:
void resizeEvent(QResizeEvent* event)
{
QLabel::resizeEvent(event);

QPixmap pixmap(size());
pixmap.fill(Qt::transparent);
QPainter::setRedirected(this, &pixmap);
QPaintEvent pe(rect());
paintEvent(&pe);
QPainter::restoreRedirected(this);
setMask(pixmap.mask());
}
};

int main(int argc, char* argv[])
{
QApplication a(argc, argv);
QLabel* label = new MaskedLabel();
label->setText("Qt Centre!");
QFont font = label->font();
font.setPointSize(72);
label->setFont(font);
label->show();
return a.exec();
}

Hi,

I tired this approach to create Picture In Picture(PIP) window on QWebView widget. And my goal is to create hole on QwebView so that video playing in the background is visible through PIP window.

When I first create this Masked Label its showing me the video playing in background, all is good at this point. But when I try to change the height/width of the Masked Label using setGeometry() method of QLabel, its is not showing me transparent window. But when I only(not changing the height/widht) move it around on the screen using same setGeometry(), it just work fine.

Any idea OR approach to achieve my goals.

Thanks.