QWidget paint event draw over children
-
I have a custom subclass of
QTabWidget
. The tab widget containsQTextEdit
widgets as children. I would like to render rectangles on the side of my tab widget to indicate when a drop action is possible. For that purpose, I overwrite theQTabWidget::paintEvent()
function:void TabWidget::paintEvent(QPaintEvent* event) { // Default rendered QTabWidget::paintEvent(event); // Render the drop zone rect (if any) if (!_dropZoneRect.isNull()) { QPainter painter(this); painter.setPen(Qt::NoPen); painter.setBrush(QBrush(Qt::lightGray)); painter.drawRect(_dropZoneRect); } }
The problem that I am facing is that it appears that the children of the tab widget are getting painted AFTER the
TabWidget::paintEvent()
function has been called. Therefore, I see my rectangle around the border of theTabWidget
but theQTextEdit
children are painted above that.
How can I paint something above my customQTabWidget
so that it covers the child widget too?Thanks for the help.
-
There's no way to paint over child widgets in the parent class (that I know of). You would need an "overlay" widget i.e. a widget that is positioned exactly above your tab widget and draw the rectangle there (something like what QRubberBand does). Since you use it only while a drag is happening it shouldn't be a problem. No need to worry about resizing and other events since a drag is happening.
-
Well that's unexpected...
May I ask what the reason for this behavior is? I would have expected that theQTabWidget::paintEvent()
renders the tab widget and it's children and after that I can perform my drawing operation which will (obviously?) occur above what has been drawn before.Anyway, I got it doing what I want it to do by following your advice of rendering a widget on top of the tab widget. For some reason I don't like this solution but as long as that is the way that I am supposed to do it I can life with it :)
-
@Joel-Bodenmann said:
May I ask what the reason for this behavior is?
This might be answered by the developers, I for one don't know the internals so well. I would assume that the paint event is sent only to the relevant widgets (based on geometry) for performance (e.g. you don't need to repaint widgets that hadn't been obscured by other windows and then exposed).
I would have expected that the QTabWidget::paintEvent() renders the tab widget and it's children and after that I can perform my drawing operation which will (obviously?) occur above what has been drawn before.
QTabWidget::paintEvent
paints only the tab bar, not the children it contains. But in any case I don't know of a widget that explicitly repaints it children. I believe Qt sends the appropriate paint events to all affected widgets based on their geometry (i.e. depending on the "dirty" region).Kind regards.
-
@kshegunov Thank you for the information. Much appreciated!
-
@Joel-Bodenmann
Well, it's mostly speculation, but you're welcome. :) -
@Chris-Kawa It turned out that
QRubberBand
is EXACTLY what I wanted. I am now using that successfully to display the drop zones. Thank you for introducing me to that :)