How to make a child widget be transparent for mouse events?
-
I have a widget named X, which is a direct child of a QScrollArea. X has a layout, and there is widget named Y in this layout.
Setting Qt::WA_TransparentForMouseEvents for widget X works, but then other widgets in X's layout are not clickable, which is a problem for me.
But if I set Qt::WA_TransparentForMouseEvents only for widget Y, then it doesn't work, I don't now it is intentional or a bug.
How to make widget Y be transparent for mouse events? -
@fokhagyma it does work as stated in the documentation:
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.
Emphasis mine.
So as @Pl45m4 wrote, you will have to implement that logic yourself or redesign your widget so that the buttons in question are not part of the transparent widget.
-
@fokhagyma said in How to make a child widget be transparent for mouse events?:
But if I set Qt::WA_TransparentForMouseEvents only for widget Y, then it doesn't work
"Doesn't work" is not a helpful description of the issue. What happens exactly?
Ideally you create a minimal example which reproduces your situation below. -
@Pl45m4 By "Doesn't work" I mean that widgets behind widget Y are not clickable which otherwise are clickable.
Here is in code what I talked about:auto X = new QWidget(top_scroll_area); auto X_layout = new QHBoxLayout(X); auto Y = new QWidget; Y->setAttribute(Qt::WA_TransparentForMouseEvents, true); X_layout->addWidget(Y); // more widgets added to X_layout
With the code above, widgets (which do not necessarily be the same all time) behind Y are not clickable. But if I set the same attribute with the same value for widget X, then widgets behind Y are clickable, but then, the other widgets in X_layout are not clickable which is not what I want. So, I want that widget behind Y are clickable and at the same time, widgets of X_layout other than Y are clickable.
-
@fokhagyma said in How to make a child widget be transparent for mouse events?:
So, I want that widget behind Y are clickable and at the same time, widgets of X_layout other than Y are clickable.
By setting
Y->setAttribute(Qt::WA_TransparentForMouseEvents, true);
you make all childs of
Y
also transparent.The way you describe it you can't use the
WidgetAttribute
here. Maybe it requires custom handling via event filter or something...
"Ignore events for Y area, but if in Y AND child of Y was hit, DONT ignore" -
@Pl45m4 Sorry, but I have to clarify some things. In my problem, Y has no child widgets, it is an empty or placeholder widget. To make things clear, here is an extended example:
auto top_scroll_area = new QScrollArea; auto W = new QWidget; auto W_layout = new QVBoxLayout(W); W_layout->addWidget(new QPushButton("xd")); W_layout->addWidget(new QPushButton("abc")); // add more widgets to W_layout ... top_scroll_area->setWidget(W); auto X = new QWidget(top_scroll_area); auto X_layout = new QHBoxLayout(X); auto Y = new QWidget; Y->setAttribute(Qt::WA_TransparentForMouseEvents, true); X_layout->addWidget(Y); auto Z = new QPushButton("v"); X_layout->addWidget(Z); // more widgets added to X_layout ...
So, as can be seen, widget X is "floating above" widget W. Without setting attribute, if X is floating above the QPushButtons of W then these buttons are not clickable. If I set to X that:
X->setAttribute(Qt::WA_TransparentForMouseEvents, true);
then buttons of W are clickable. But in this case, button Z in the X_layout is not clickable, which is bad for me.
I only want, that buttons of W which happens to be behind widget Y are clickable, but if these buttons are behind Z, then only Z is clickable. In other words, if the clickable items of W located in the area of Y, then these items are clickable, but if these items are under the siblings of Y (e.g. Z), then the siblings of Y should get the click event not the items under the siblings.
The straightforward solution would be:Y->setAttribute(Qt::WA_TransparentForMouseEvents, true);
but this doesn't work.
-
@Pl45m4 said in How to make a child widget be transparent for mouse events?:
Maybe it requires custom handling via event filter or something...
"Ignore events for Y area, but if in Y AND child of Y was hit, DONT ignoreAs I've said here, your requirements can't seem to be met by just setting one of the attributes, since your "logic" isn't straightforward. So you probably have to figure it out manually.
-
@Pl45m4 You said: "your "logic" isn't straightforward" I don't think so. My problem is simple, there is a widget which I want to be transparent for mouse events, this works for some widgets e.g. in the example works for widget X, but why does not work for widget Y? It seems that Qt's logic isn't straightforward.
-
@fokhagyma it does work as stated in the documentation:
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.
Emphasis mine.
So as @Pl45m4 wrote, you will have to implement that logic yourself or redesign your widget so that the buttons in question are not part of the transparent widget.
-
@SGaist I reread and reinterpreted the quoted statement in your post and finally got it why Qt::WA_TransparentForMouseEvents does not work for widget Y as I expected. The key part is "as if the widget and its children were not present in the widget hierarchy", so if Y is not present, then widget X will get a mouse event, which is not transparent, so mouse event won't go through X. Thanks.
-