Nominate our 2022 Qt Champions!

QWidget::render() in custom QWidget

  • Moderators

    Hello everyone,

    I made a custom QStackedWidget with the purpose of an animated transition from one widget to another - Slide in and out.

    I had issues with moving the QWidgets directly so I decided to make a screenshot of the new and old widget, show those, and move them with a QParallelAnimationGroup.

    I did this the following way:

        QPoint pNext = widget(slideTo)->pos();
        pNow = widget(iCIndex)->pos();
        QPixmap pmCurrent = QPixmap(widget(iCIndex)->size());
        QPixmap pmSlideTo = QPixmap(widget(slideTo)->size());
        QLabel *lblCurrent = new QLabel(this);
        QLabel *lblSlideTo = new QLabel(this);
        lblCurrent->show(); lblSlideTo->show();
        lblCurrent->raise();     lblSlideTo->raise();
        lblSlideTo->move(pNext.x() - iOffsetX, pNext.y()-iOffsetY);
        QPropertyAnimation *anCurrent = new QPropertyAnimation(lblCurrent,"pos");
        QPropertyAnimation *anSlideto = new QPropertyAnimation(lblSlideTo,"pos");
        QParallelAnimationGroup *anGroup = new QParallelAnimationGroup;
        connect(anGroup, &QParallelAnimationGroup::finished, lblCurrent, &QLabel::deleteLater);
        connect(anGroup, &QParallelAnimationGroup::finished, lblSlideTo, &QLabel::deleteLater);
        connect(anGroup, &QParallelAnimationGroup::finished, [=]{
           bActive = false;
           emit AnimationFinished();

    The problem is, QWidget::render() completely ignores the stylesheet of the cStackedWidget. I applied it with


    from the GUI-Class. The white background does not show in the QDesigner, but it is correctly painted when I start the program.

    If I set a global StyleSheet like


    then render() accepts the white background. However I don't want to/can't use that , because it would overwrite the children of the whole ui.

    From the docu I know, that I have the overwrite the paintEvent in my custom widget class, which I did:

    void cStackedWidget::paintEvent(QPaintEvent *)
        QStyleOption opt;
        QPainter p(this);
        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);

    So, I'm kinda lost and out of ideas, if anyone could help me, I would be very grateful.

    If needed/asked for, I'll look in uploading the class so it can be tested easily!?

  • Lifetime Qt Champion


    I think the issue is just who is parent ?
    The stylesheet will affect children so if it works with the custom widget when
    has the style so to speak
    then it sounds like your custom is just owned by something not affected and hence its children will no either.

    I use only a single stylesheet on mainwindow. Not pr control as i think it becomes uncontrollable very fast.

    Maybe i misunderstand your issue and what works and what do not work.
    Your paint looks correct :)

  • To add to @mrjj

    @J.Hilk said in QWidget::render() in custom QWidget:

    However I don't want to/can't use that , because it would overwrite the children of the whole ui.

    You can use object name specific stylesheet see id selector in

    I had issues with moving the QWidgets directly

    I implemented something similar here SelettoreImmagini.h SelettoreImmagini.cpp it's from one of the very first programs I wrote in Qt (a snake game) so it's VERY far from good (and the variable names are in italian) but gives you an idea, basically you keep 1 widget always visible then, you add the widgets that you want to scroll as its children but you never add them to a layout but instead manually resize them to the parent widget, at this point you are free to animate the "pos" property of the child widgets. In the linked example I move 2 QLabels

  • Moderators

    @VRonin @mrjj

    Hi, sorry for the delay, was a crazy weekend on my side. Thanks for the fast replies

    I think I'll have to be more precise with my description.

    First off, you may find a small example project here.

    So, let's say I set a single StyleSheet on the QMainWindow, like this:


    I get a exactly what I want, white background/Mainwindow, red Stackedwidget and blue labels.
    As soon as I use render() on the first QWidget of the QStackedWidget. the red is completly ignored, I get the default light grey for the stacked widget and blue QLabels

    When I set the StyleSheet like this:


    Everything is Red but, render() actually captures the QStackedWidget color correctly.


    As I'm writing this, I actually find the crux of the problem.



    Paints the ui, like I whoud expect it to but its apparently not doing the job thoroughly enough.
    Each "page" of the QStackedWidget is a QWidget, and using the above code paints the QWidgets red as well but not for the QWidget::render() function.

    Using this StyleSheet:


    I see no difference for when the widget is painted, but now QWidget::render actually accepts the red background.

    So, is this a bug ot intended behaviour?

  • Lifetime Qt Champion

    Super with a sample. +5
    I see what you mean.
    Its a bit odd. So first it accepts the stylesheet but when
    you render an image for slide animation it is
    not applied. I thought it would be exactly the
    same in and render() would just call paint.

    Interesting :)

  • Moderators

    Just realized, that I had still thread still open.

    I'll share how I managed to circumvent the problem. Sadly I haven't found a real solution as of now.

    In the function that makes the screenshot, I added this line just before calling QWidget::render

    this->setStyleSheet("cStackedWidget {background-color:white;}"
                            //List of all  QStackedwidget Pages

    For some reason I have to set the stylesheet new for each time. Simply setting this once will not work.

    Anyway, I'll mark it as solved,
    unless someone else has a new idea !?