Draw Rectangular overlay on QWidget at click
Asked Answered
H

2

15

in my project i use a EventFilter for widgets, that are in a QHBoxLayout.

If i clicked on an a widget, i want to draw a transparent overlay with blue color over the clicked widget. Is there a way to implement this?

greetings

Hickox answered 5/10, 2013 at 16:15 Comment(0)
A
26

This answer is in a series of my overlay-related answers: first, second, third.

One way of doing it is:

  1. Have a semi-transparent overlay widget that is also transparent to mouse events.

  2. In the event filter, track the clicks and the resizing of the objects by adjusting the overlay's geometry to match that of the target widget.

The self-contained example below works under both Qt 4 and Qt 5 and does what you want.

screenshot

// https://github.com/KubaO/stackoverflown/tree/master/questions/overlay-19199863
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif

class Overlay : public QWidget {
public:
    explicit Overlay(QWidget *parent = nullptr) : QWidget(parent) {
        setAttribute(Qt::WA_NoSystemBackground);
        setAttribute(Qt::WA_TransparentForMouseEvents);
    }
protected:
    void paintEvent(QPaintEvent *) override {
        QPainter(this).fillRect(rect(), {80, 80, 255, 128});
    }
};

class OverlayFactoryFilter : public QObject {
    QPointer<Overlay> m_overlay;
public:
    explicit OverlayFactoryFilter(QObject *parent = nullptr) : QObject(parent) {}
protected:
    bool eventFilter(QObject *obj, QEvent *ev) override {
        if (!obj->isWidgetType()) return false;
        auto w = static_cast<QWidget*>(obj);
        if (ev->type() == QEvent::MouseButtonPress) {
            if (!m_overlay) m_overlay = new Overlay;
            m_overlay->setParent(w);
            m_overlay->resize(w->size());
            m_overlay->show();
        }
        else if (ev->type() == QEvent::Resize) {
            if (m_overlay && m_overlay->parentWidget() == w)
                m_overlay->resize(w->size());
        }
        return false;
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    OverlayFactoryFilter factory;
    QWidget window;
    QHBoxLayout layout(&window);
    for (auto text : { "Foo", "Bar", "Baz "}) {
        auto label = new QLabel{text};
        layout.addWidget(label);
        label->installEventFilter(&factory);
    }
    window.setMinimumSize(300, 250);
    window.show();
    return a.exec();
}
Arbitration answered 5/10, 2013 at 19:40 Comment(0)
C
3

In the overlay widget constructor:

    setWindowFlags(Qt::Widget | Qt::FramelessWindowHint | Qt::ToolTip | Qt::WindowStaysOnTopHint);
    setAttribute(Qt::WA_NoSystemBackground, true);
    setAttribute(Qt::WA_TranslucentBackground, true);

In the window that owns that widget:

overlay_ = new RtspOverlay(this);
overlay_->show();
Corvus answered 28/2, 2017 at 17:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.