krojew
krojew

Reputation: 1336

Painting QWidgets by their parent

I have a rather unsual situation - I have a widget with child widgets and I need the painting of the children to be done by the parent, bypassing Qt 5 paint system. In detail: there is a QWidget which has an OpenGL context and it does its painting in normal paintEvent():

    mRenderer->activate();
    mRenderer->preRender();
    mRenderer->setClearColor(Color(0.75f));
    mRenderer->clear(Renderer::CLEAR_Color);

    QList<RendererWidgetWrapper *> wrappers = findChildren<RendererWidgetWrapper *>();
    foreach (RendererWidgetWrapper *wrapper, wrappers)
        wrapper->paint();

    mRenderer->postRender();

where mRenderer is a wrapper for OpenGL (or any other possible 3D renderer). Note that it explicitly calls paint() on its children. This paint() function just renders some things using mRenderer, therefore bypassing normal Qt paint pipeline. The parent widget has some attributes set:

    setAttribute(Qt::WA_PaintOnScreen);
    setAttribute(Qt::WA_NoSystemBackground);
    setAttribute(Qt::WA_OpaquePaintEvent);
    setAttribute(Qt::WA_PaintUnclipped);

and returns nullptr as its QPaintEngine. The children also return nullptr as QPaintEngine, but do not set any attribute other than Qt::WA_NoSystemBackground and Qt::WA_OpaquePaintEvent. In short - the whole thing is a method of having hundreds of widgets rendering to one OpenGL context owned by their parent, to avoid killing the system with many contexts. The problem with this method is that the children are all black. Something is clearing their visible area and I have no idea how to make this blackness disappear. Does anyone have any idea what to do with it?

EDIT:

Using setUpdatesEnabled(false); removed the black background but now the area of the child widgets is not updated. Instead is contains what was visible on screen previousely.

EDIT 2:

I found that Qt creates native children windows if the parent has Qt::WA_PaintOnScreen attribute, which causes the problem. So now the question is how to avoid it, while forcing the parent to become a native window?

Upvotes: 2

Views: 1822

Answers (1)

Ilya Kobelevskiy
Ilya Kobelevskiy

Reputation: 5345

If you want to bypass paint event for your children, you can re-implement

virtual void    paintEvent ( QPaintEvent * event );

for them. Like that:

.h

class QWidgetNoPaintEvent : public QWidget
{
   //reimplement all ctors here
   virtual void paintEvent ( QPaintEvent * event );
}

.cpp

void QWidgetNoPaintEvent::paintEvent ( QPaintEvent * event )
{
 //do nothing, or reject event, or do something custom ???
}

I'm not 100% sure if it will solve other problem though, since it will only block paint events through Qt for widgets inherited from QWidgetNoPaintEvent.

Upvotes: 0

Related Questions