jump to navigation

Qt tip & Trick: Masking Widgets December 13, 2010

Posted by tumaix in planetkde-tomazcanabrava.
trackback

Have you ever tried to create an overlay on top of some QWidgets to make them not acessible, but still visible to the user? I’m not saying about setEnabled(false), but to create a semitransparent – mask on top of some widgets with something inside, a modal dialog or so.

I was yesterday at #qt trying to figure out how to do that, aseigo had already told me that it was possible  by using a QGraphicsView as the mask widget with a transparent background, so I did this:

[snip]

view->scene()->setSceneRect( w->rect() );
view->setFixedSize( w->size() );
view->setFrameStyle( QFrame::NoFrame );
view->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
view->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
view->setBackgroundRole( QPalette::Window );
view->setBackgroundBrush(QBrush(QColor(122,122,122,122)));
view->setAutoFillBackground( true );

[/sniṕ]

this was doing almost, but not quite, not what I wanted. It correctly paced the QGraphicsView on top of the widgets, no scalling, but it was opaque. then Leo Franchi came to the rescue.

QPalette p = view->palette();
p.setColor( QPalette::Window, Qt::transparent );
view->setPalette( p );

that way, the QGraphicsView was alpha-transparent on top of my widgets, and a nice mask-effect was given.

but beware that this approach does not handle resizing since the item does not belong to any QLayout, not a problem with Qt, since you can manage to make that happen using a eventFilter:

bool KWelcomeWidget::eventFilter( QObject* obj, QEvent* event ){
if( event->type() == QEvent::Resize ) {
QWidget *parentWidget = static_cast<QWidget*>(obj);
QGraphicsView *view = static_cast<QGraphicsView*>(d_ptr->m_part->widget());
view->scene()->setSceneRect( parentWidget->rect() );
view->setFixedSize( parentWidget->size() );
setFixedSize(parentWidget->size());
return false;
}
return QObject::eventFilter( obj, event );
}

 

Comments»

1. Eike Hein - December 13, 2010

If you want something visible but truely not accessible, it’s far easier to put one QWidget above another and set the Qt::WA_TransparentForMouseEvents hint on the top widget. Then it’s visible, but mouse events go through it to the lower widget.

That’s what Yakuake’s visual event overlay does, which is used to display various effects on top of the terminal widget of the Konsole KPart component, since Yakuake can’t access that widget’s paint event.

tumaix - December 13, 2010

that way I was just making a mask, but by using a QGraphicsView I can add graphics items on it and make it behave like a modal dialog. for instance to create a “WelcomeDialog” in the middle of the mainWidget

2. Leo S - December 13, 2010

Why do you need a QGraphicsView? Is the same not possible with a simple QWidget?

tumaix - December 13, 2010

persons from #qt told me it was not possible 😉

3. Aurélien Gâteau - December 13, 2010

If I am not mistaken, setting the QPalette::Window role of the palette to a color which is not fully opaque should work with all widgets. You don’t need to use a QGraphicsView.

tumaix - December 13, 2010

true thing, but by using a QGraphicsView I can use a different collor as the mask

Aurélien Gâteau - December 14, 2010

I am not sure what you mean with “a different color as the mask”, the background color can be any color you want.

tumaix - December 14, 2010

actually I just followed aseigo and lfranchi while trying to do that ( despite people from #qt saying that was not possible ), aseigo’s and lfranchi’s approach used a QGraphicsView with an alpha background, I tougth it was just that way that way that makes it possible.

4. Gökmen Göksel - December 15, 2010

Hi,
I’ve made similar things with just using a QWidget and style as backround-color:rgba(0,0,0,100) 😉

Here is the result http://www.vimeo.com/16763092

You can grab the code from http://svn.pardus.org.tr/uludag/trunk/pds/ (it is PyQt)

tumaix - December 15, 2010

cool. =D
for mine, I really have to use a QGraphicsView since I’m using plasma to show some stuff, tought.

5. Camila San - December 17, 2010

desenvolver isso em html pode ser tão “xarope” quanto em Qt.
:*

6. Lata Agrawal - November 2, 2011

I am trying to create an application in QT in which I want to overlay some buttons on top of a video (which may be played using Phonon media player or Coreplayer media player). Can you help me how should I go about it? I cannot use OpenGL as the embedded device for which I am making this app does not support

tumaix - November 3, 2011

you can use a QGraphicsView and use your widgets inside it, thus, making a overlay.

Lata Agrawal - November 3, 2011

I used QgraphicsView and added my overlay (inherited from QWidget, with a button) as a scene to it. I also added the VideoWidget in which Phonon player is playing the video as a scene to the view. But the area where it overlaps the video area is black. The button on the overlay is seen properly.
I have also tried QStackedLayout but the same output. How to get rid of this black background of the overlay?


Leave a comment