Creating a translucent QWidget
Written on September 28, 2009, by Milot Shala.

In my earlier post, I mentioned writing my personal video player so I wrote it and I’m working on it whenever I have time.

There are several cool video players out there with great user experience and one of them is VLC which has an awesome OSD (On Screen Display), for long I wanted this feature on my player.

This blog post is a step by step guide on how to create a rectangular semi-transparent widget that looks similar to VLC’s OSD.

Note: Result in the end is not exactly as seen in VLC screenshot above, but the widget can be adjusted more to look like it, and when a video is playing in full screen, the widget will look prettier as well.

Semi transparent widgets can be created using Qt’s backing store feature introduced in Qt 4.1. For more information on Transparent Backgrounds in Qt read this article.

For implementing a custom widget we start by inheriting QWidget class as shown in Listing 1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class CoolWidget : public QWidget
{
public:
    CoolWidget(QWidget *parent = 0);
 
protected:
    void paintEvent(QPaintEvent *pnt);
    void mouseMoveEvent(QMouseEvent *evt);
    void mousePressEvent(QMouseEvent *evt);
 
private:
    QPoint dragging_position;
    QColor current_color;
    QPushButton *cool_wdg_button[5];
 
};

Listing 1.

In CoolWidget class, mouseMoveEvent, mousePressEvent and paintEvent virtual members should be overridden in order to have implementation of specific features of this custom widget, below is the explanation of use for each virtual member:

mouseMoveEvent is used to move the widget.
mousePressEvent is used to get the QPoint where mouse position started dragging the widget.
paintEvent is used to paint the widget in our own way (to achieve our purpose of creating rectangular semi-transparent widget).

In paintEvent, QPainter and QPen classes are instantiated. QPainter and QPen classes are used for painting and drawing rectangular borders around the widget. After instantiating QPen, it’s width and styles are set. In CoolWidget’s case SolidLine pen style is used with RoundJoin as join style and SquareCap as cap style.

After adjusting QPen, alpha value of QColor class instantiated as current_color (See Listing 1) must be set to 100 via QColor::setAlpha method, then use QPainter class’ fillRect method by passing rect() and the current_color as parameters, then CoolWidget will get a semi-transparent background. In the constructor of CoolWidget’s current_color is set to Qt::black. See Listing 5.

We pass QPen to QPainter::setPen() and draw the rectangle using rect() method.

Implementation of paintEvent is shown in Listing 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void CoolWidget::paintEvent(QPaintEvent *pnt)
{
    QPainter painter(this);
 
    QPen pen;
    pen.setWidth(10);
    pen.setStyle(Qt::SolidLine);
    pen.setJoinStyle(Qt::RoundJoin);
    pen.setCapStyle(Qt::SquareCap);
 
    current_color.setAlpha(100);
 
    painter.fillRect(rect(), current_color);
    painter.setPen(pen);
    painter.drawRect(rect());
}

Listing 2.

mousePressEvent is about giving dragging_position a value, which is the subtraction of global position with top left corner of widget’s frame geometry as shown in Listing 3.

1
2
3
4
5
6
7
8
void CoolWidget::mousePressEvent(QMouseEvent *evt)
{
    if(evt->button() == Qt::LeftButton)
    {
        dragging_position = evt->globalPos() - frameGeometry().topLeft();
        evt->accept();
    }
}

Listing 3.

mouseMoveEvent is about moving the widget. Widget movement is done using move() method, by passing global position QPoint subtracted by dragging_position QPoint as shown in Listing 4.

1
2
3
4
5
6
7
8
void CoolWidget::mouseMoveEvent(QMouseEvent *evt)
{
    if(evt->buttons() == Qt::LeftButton)
    {
        move(evt->globalPos() - dragging_position);
        evt->accept();
    }
}

Listing 4.

In constructor the widget is resized to 300×300, current_color is set to black and 5 QPushButtons are created as shown in Listing 5.

1
2
3
4
5
6
7
8
9
10
11
12
13
CoolWidget::CoolWidget(QWidget *parent)
        : QWidget(parent)
{
    current_color = Qt::black;
 
    resize(300, 300);
 
    for(int i = 0; i < 5; i++){
        cool_wdg_button[i] = new QPushButton(QString("Cool Button %1").arg(i), this);
        cool_wdg_button[i]->move(10, i * 40);
    }
 
}

Widget is used with the following snippet:

1
CoolWidget *coolwdg = new CoolWidget(this);

And CoolWidget in action:

If you find this post useful or have questions regarding the topic, don’t hesitate to either to leave a comment or write me an email at: milot.shala [at] gmail [dot] com

  • Swetha

    Hi,

    i tried out your code in my system but the transparency does not work.I am using Qt 4.6.Do you have any idea what else i can do for the transparency.
    regards
    -swetha

  • http://spartansoft.org Milot Shala

    Hi Swetha,

    In what operating system have you tried? and what are you using as your parent widget?

    I compiled it on a Mac and against Symbian simulator it works: http://twitpic.com/2ooe0t and http://twitpic.com/2oofbe

    Can you give me more details and I will try to reproduce the problem.

  • http://mms-core.weebly.com/ MamdouhAlShamy

    Hi,
    it doesnt work for my either ,when i try the widget become black

    am on Win7,Qt 4.7

    regards
    MamdouhAlShamy

  • http://mms-core.weebly.com/ MamdouhAlShamy

    hi,
    it doesnt work for me either,
    im working on Windows7 with Qt 4.7 on QWidget with parent Widget

    when i use this code ,i get black background for the desired widget

    reagards

blog comments powered by Disqus

4,426 views

© Copyright Phalanx Blogosphere - Powered by Wordpress - Phalanx logo is designed by Leopard Cana