Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw Rectangular overlay on QWidget at click

Tags:

qt

qwidget

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

like image 585
501 - not implemented Avatar asked Oct 05 '13 16:10

501 - not implemented


1 Answers

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();
}
like image 72
Kuba hasn't forgotten Monica Avatar answered Sep 18 '22 07:09

Kuba hasn't forgotten Monica