Drawing composed widget
-
I'm working on a customly drawn widget right now, which consists out of multiple sub-elements.
Each child-widget (separate code file / class) has its ownpaintEvent
and is drawn using aQPainterPath
or just by simpleQPainter::drawRoundedRect
.
One of them is some kind of border/"halo" around the main widget.Looks about like this (simplified)
For that, the sub-element (yellow frame) has the exact same size as the parent (gray rounded rect), since the childs geometry/boundings can't exceed the parents coordinate system (for obvious reasons).
The problem I have is that I want to interact with the different sections (subwidgets) of the widget.
Doing that, if I click for example on the yellow border, some signal is emitted... works fine so far.
However one of the signals (inmousePressEvent
of the border child is also emitted when clicking the "hole"... the area where the child border widget is not drawn, because it's within the widget's boundings...Maybe my way of doing this is wrong and there is a better way, but I'm looking for a solution to paint the border on top of the main widget with some kind of hole in the middle, so that user interactions (mouse hover, mouse clicks) only affect the actual "painted" area and not the invisible one, which became part of the child widget.
No problems with the other child widgets, but since this specific one has a ring structure along the edge of the main widget, I don't know any other way than doing it the way I've tried.Open for any suggestions :)
-
Solved.
For further readers:
I've added a check to the child widget whether a user interaction happens within its drawn borders (a closedQPainterPath
).
If so, I consume the event and continue from there, if not, I ignore the event and pass it to the parent widget, i.e. the actualMyWidget
, so that the overlaying child widget has some transparency for my defined events (some key and mouse interaction).Pretty easy if I think about it now.
The idea of having some kind of a donut shaped widget (yellow part in my sketch), which does not occupy the center of its parent widget was stuck in my head way too long :)) -
Hi @Pl45m4
Maybe Have a try with:
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. -
@mpergand said in Drawing composed widget:
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.Is this "hacking" or is this how one would do this in general?!
I mean, my idea overall is pretty standard I would say, but haven't found any example of some custom (not using anyQStyle::drawPrimitive or ::drawComplex)
composed widget, built the way I thought of...but for sure nothing new.
So basicallyMyWidget
is parent of widgetBorder
and other painted child widgets, that are hidden from the user ofMyWidget
.I'm actually not that familiar with a more complex and structural use of
QPainter
.
My first approach was painting every sub-region (borders etc.) inside the one widget'spaintEvent
... and then differ where exactly the user interaction has happened... but that was a complete mess and I couldn't catch mouse events as easy as I can now that my widget has its own internal child widgets (as separate classes).Edit:
I think I can't useQt::WA_TransparentForMouseEvents
anyway since all child widgets and including the main widget need to receive mouse events at some point. But only in regions where their painting is active. -
* BUMP *
No suggestions?!
I would be happy if someone could confirm that it is not possible what I'm trying to do (no way) or that I am on the wrong track with my approach (possibly).
It actually seems so simple, but somehow I'm failing to properly draw my widget.
Edit:
Will add some code later, showing what I have so far.
-
Solved.
For further readers:
I've added a check to the child widget whether a user interaction happens within its drawn borders (a closedQPainterPath
).
If so, I consume the event and continue from there, if not, I ignore the event and pass it to the parent widget, i.e. the actualMyWidget
, so that the overlaying child widget has some transparency for my defined events (some key and mouse interaction).Pretty easy if I think about it now.
The idea of having some kind of a donut shaped widget (yellow part in my sketch), which does not occupy the center of its parent widget was stuck in my head way too long :)) -