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);
NormalWidget window;
window.resize(500,500);
window.setObjectName("window");
window.setStyleSheet("background-color: rgba(0,0,128,128); ");
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>
class TransparentWidget : public QWidget
{
Q_OBJECT
public:
explicit TransparentWidget(QWidget *parent = 0): QWidget(parent)
{
setAttribute(Qt::WA_TransparentForMouseEvents);
}
~TransparentWidget(){}
protected:
QRect opaqueRect = QRect(0,0,400,100);
void paintEvent(QPaintEvent *)
{
QRegion reg(opaqueRect);
setMask(reg);
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 ||
event->type() == QEvent::MouseButtonRelease)
{
QMouseEvent* e = static_cast<QMouseEvent*>(event);
if (e && !opaqueRect.contains(e->pos()) return false;
}
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>
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