How to disable the delivery of mouse events to the widget but not its children in Qt?

Shuji picture Shuji · Jan 9, 2015 · Viewed 8.3k times · Source

For the last two days, I've been searching for a way to pass mouse events to the widgets behind a widget used as a container/parent for it's children. I know there is a way to make a widget transparent for mouse events like this:

QWidget w;
w.setAttribute( Qt::WA_TransparentForMouseEvents );

But this also disables the delivery of mouse events to its children! I want the children of the front widget and the widgets behind the front widget to receive the mouse events.

Qt::WA_TransparentForMouseEvents: When enabled, this attribute disables the delivery of mouse events to the widget and its children. Mouse events are delivered to other widgets as if the widget and its children were not present in the widget hierarchy; mouse clicks and other events effectively “pass through” them. This attribute is disabled by default.

If you have any idea about how to make a widget transparent for mouse events but not it's children then please share!

Answer

Shuji picture Shuji · Jan 9, 2015

At last I found a solution :)

QWidget::setMask ( const QRegion & region )

https://doc.qt.io/qt-5/qwidget.html#setMask-1

http://qt-project.org/doc/qt-4.8/qwidget.html#setMask

I found the solution here: http://www.qtcentre.org/archive/index.php/t-3033.html

QRegion reg(frameGeometry());
reg -= QRegion(geometry());
reg += childrenRegion();
setMask(reg);

Now children of the front widget and the widgets behind the front widget respond to the mouse events as required!

Remember, you would need to call these lines again whenever the front widget is re-sized to recalculate the geometry for the mask!

void someWidget::resizeEvent(QResizeEvent *e){
  QWidget::resizeEvent(e);
  QRegion reg(frameGeometry());
  reg-=QRegion(geometry()); 
  reg+=childrenRegion();
  setMask(reg);
}