PDA

View Full Version : Qt4.1 Transparent Widget



djoul
18th July 2006, 12:12
Yeah, you must think another boring thread lost in the 1000000 threads on transparent backgrounds.
But I've spent a long time reading a lot of threads and no one is clear, simple, easy to understand for a new Qt progammer, like if there are a hundred different solutions with alpha blending, qpalette, ....
So what I want to achieve is EXACTLY that :

http://www.qtforum.org/attachment.php?attachmentid=798

and if during my program the destokp background change so does the widget.
So I don't need setWindowOpacity, I've tried all the stuff with the Palette, trying to put a blanck png pixmap on the background, nothing seems to work (or I do it bad ...)

The solution would have been that the guys form Qt put the source code for that exemple :

http://doc.trolltech.com/qq/qq16-background.html
which fit my problem but they haven't.

So anyone has an understandable solution for my problem ???

wysota
18th July 2006, 12:56
Use QWidget::setMask() to tell the widget which parts of it should be opaque and the rest will be transparent. The only difficulty is that whenever you resize the widget, the mask has to change too, so you have to attach to some event and re-set the mask after the layout does its job to reposition widgets.

jpn
18th July 2006, 13:24
Override QWidget::resizeEvent (http://doc.trolltech.com/4.1/qwidget.html#resizeEvent)(). Here's a pseudo algo:



resizeEvent
{
// include title and frames
region = frameGeometry // frameGeometry relative to the widget (not global)

// exclude the area inside frames
region -= geometry // geometry relative to the widget (not global)

// include children
region += childrenRegion

// apply mask
setMask region
}


PS. The indexing feature in Qt Assistant is powerful. Try entering "keywords" used in above pseudo code..

djoul
18th July 2006, 14:04
My widget won't be resized, it's just a gridlayout with buttons on a backgroud. and I just want the buttons to be shown.
I'm digging the setMask way, now I have just the border of the widget that is transparent, but my layout with the buttons are still shown, I'm trying to let the layout transparent.
I haven' implemented the QpaintEvent as I use the setMask inthe constructor, should I use a png pixmap with a timer to call paintEvent to refresh the layout and make it transparent ?

wysota
18th July 2006, 14:07
No. Don't touch the paint event. You only need setMask() just like jpn suggested. And better put it in resize event and not in the constructor, just in case. But it should still work with the constructor (the same contents as in the resize event).

djoul
18th July 2006, 15:48
Ok, one last (stupid) question :
With the region stuff, adding and taking off some parts, I need to know the position of my buttons to tell the mask not to take them.
But as I use them with a Layout, that s the layout which knows where exactly they are and I don t have an idea about how knowing their coordonates, pushbutton1.x() does not exists ...

wysota
18th July 2006, 15:51
QWidget::childrenRegion()

djoul
18th July 2006, 16:22
Override QWidget::resizeEvent (http://doc.trolltech.com/4.1/qwidget.html#resizeEvent)(). Here's a pseudo algo:



resizeEvent
{
// include title and frames
region = frameGeometry // frameGeometry relative to the widget (not global)

// exclude the area inside frames
region -= geometry // geometry relative to the widget (not global)

// include children
region += childrenRegion

// apply mask
setMask region
}


PS. The indexing feature in Qt Assistant is powerful. Try entering "keywords" used in above pseudo code..
I'm really a dumbass, can you give the code of the image you attached, it would be much better to understand and help me stopping yelling against my computer.
I m too young to have white hair !!!

wysota
18th July 2006, 16:28
I think the code is more or less like this:


void someWidget::resizeEvent(QResizeEvent *e){
QWidget::resizeEvent(e);
QRegion reg(frameGeometry());
reg-=QRegion(geometry()); // this may have to be different here
reg+=childrenRegion();
setMask(reg);
}

But you could have come up to that yourself, you know...

djoul
18th July 2006, 16:33
[QUOTE=wysota]I think the code is more or less like this:


void someWidget::resizeEvent(QResizeEvent *e){
QWidget::resizeEvent(e);
QRegion reg(frameGeometry());
reg-=QRegion(geometry()); // this may have to be different here
reg+=childrenRegion();
setMask(reg);
}
thanks, I had problems with the childrenRegion, I thought it gave me the region for just one button, I had to apply it to several child widgets.
The code is simple but I don t think I would have come to this quickly

Thanks again

wysota
18th July 2006, 16:45
This (almost, it eats up the window decoration too) works for me.

jpn
18th July 2006, 16:59
This (almost, it eats up the window decoration too) works for me.
It eats the window decoration because the QRect returned by QWidget::frameGeometry() and QWidget::geometry() (for a top-level widget) are relative to the global coordinate system. They must be mapped from global coordinates to the widget's own coordinate system. This is how I made it work:



// map geometries to widget's coordinates
QRect fg = frameGeometry();
fg.moveTo(mapFromGlobal(fg.topLeft()));
QRect gm = geometry();
gm.moveTo(mapFromGlobal(gm.topLeft()));

// include title and frames
QRegion region = fg;

// exclude the area inside frames
region -= gm;

// include all children
region += childrenRegion();

// apply mask
setMask(region);

Lele
19th July 2006, 10:58
I tried to have also the QPalette::Base transparent (completly or some color with alpha) but I didn't succeed, has anyone of you already tried that?
thanks

jpn
19th July 2006, 13:17
I tried to have also the QPalette::Base transparent (completly or some color with alpha) but I didn't succeed, has anyone of you already tried that?
thanks
It's not possible to make top level widgets transparent by just changing the palette. AFAIK there are only 2 possibilities; to make the whole window transparent by QWidget::setOpacity() or completely hide parts of the window by QWidget::setMask().

LarryDobson
26th September 2006, 17:06
Here is a related thread...
QDialog w/ transparent background (http://www.qtcentre.org/forum/f-qt-programming-2/t-qdialog-w-transparent-background-3757.html)