QT event transparency for part of the widget only

The software showed 3 widgets:

  • Main window
  • Content widget covering most of the main window
  • A custom widget that spans a portion of both the main window and the content widget.

The custom widget has a part (defined as QRect) that should be Event-opaque, and the surrounding area should be Event-transparent.

I tried:

setAttribute(Qt::WA_TransparentForMouseEvents);

But all sub-widgets of the user interface also become transparent.

I also tried with setMask, but then the custom widget cannot draw around the neighborhood.

How to achieve this partial transparency of events?

Example (this does not explain the complete problem, just add a base for testing solutions):

main.cpp

#include "transparentwidget.hpp"
#include "normalwidget.hpp"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // Main Window
    NormalWidget window;
    window.resize(500,500);
    window.setObjectName("window");
    window.setStyleSheet("background-color: rgba(0,0,128,128); ");

    // Content window
    NormalWidget content(&window);
    content.setObjectName("content");
    content.resize(400, 400);
    content.move(0,0);
    content.setStyleSheet("background-color: rgba(128,0,0,128);");

    TransparentWidget custom(&window);
    custom.setObjectName("custom");
    custom.resize(500, 200);
    custom.setStyleSheet("background-color:rgba(0,128,0,128);");

    window.show();

    return a.exec();
}

transparentwidget.hpp

#ifndef TRANSPARENTWIDGET_H
#define TRANSPARENTWIDGET_H

#include <QWidget>
#include <QStyleOption>
#include <QPainter>
#include <QDebug>
#include <QEvent>

// This widget shall be transparent in some parts
class TransparentWidget : public QWidget
{
    Q_OBJECT

public:
    explicit TransparentWidget(QWidget *parent = 0): QWidget(parent)
    {
        // Start of solution with WA_TransparentForMouseEvents (not working)
        setAttribute(Qt::WA_TransparentForMouseEvents);
        // end solution with WA_TransparentForMouseEvents
    }
    ~TransparentWidget(){}

protected:
    QRect opaqueRect = QRect(0,0,400,100);
    void paintEvent(QPaintEvent *)
    {
        // Solution with setMask, not working
        QRegion reg(opaqueRect);
        setMask(reg);
        // end of setMask solution

        QStyleOption opt;
        opt.init(this);
        QPainter p(this);
        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    }

    bool event(QEvent *event)
    {
        // Starting of solution with event propagation (not working)
        if (event->type() == QEvent::MouseButtonPress ||
            event->type() == QEvent::MouseButtonRelease)
        {
            QMouseEvent* e = static_cast<QMouseEvent*>(event);
            if (e && !opaqueRect.contains(e->pos()) return false;
        }
        // end solution with event propagation.

        if (event->type() == QEvent::MouseButtonPress) qDebug() << "Press: " << objectName();
        else if(event->type() == QEvent::MouseButtonRelease) qDebug() << "Release: " << objectName();

        return QWidget::event(event);
    }
};
#endif

normalwidget.hpp

#ifndef NORMALWIDGET_H
#define NORMALWIDGET_H

#include <QWidget>
#include <QStyleOption>
#include <QPainter>
#include <QDebug>
#include <QEvent>

// Widgets that are not event-transparent
class NormalWidget : public QWidget
{
    Q_OBJECT

public:
    explicit NormalWidget(QWidget *parent = 0): QWidget(parent){}
    ~NormalWidget(){}

protected:
    void paintEvent(QPaintEvent *)
    {
        QStyleOption opt;
        opt.init(this);
        QPainter p(this);
        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    }

    bool event(QEvent *event)
    {

        if (event->type() == QEvent::MouseButtonPress) qDebug() << "Press: " << objectName();
        else if(event->type() == QEvent::MouseButtonRelease) qDebug() << "Release: " << objectName();

    }
};

#endif // NORMALWIDGET_H
+4
1

:

, .

, TransparentWidget::event(). TransparentWidget, , TransparentWidget:

bool TransparentWidget::event(QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress ||
        event->type() == QEvent::MouseButtonRelease ||
        event->type() == QEvent::MouseButtonRelease)
        return false;
    else
        return QWidget::event(event);
}
0

All Articles