Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QWidget::render() in custom QWidget
QtWS25 Last Chance

QWidget::render() in custom QWidget

Scheduled Pinned Locked Moved Solved General and Desktop
qwidgetrenderingcustom widgetsstylesheet
6 Posts 3 Posters 6.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    J.Hilk
    Moderators
    wrote on 10 Mar 2017, 13:44 last edited by
    #1

    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());
        widget(iCIndex)->render(&pmCurrent);
        QPixmap pmSlideTo = QPixmap(widget(slideTo)->size());
        widget(slideTo)->render(&pmSlideTo);
    
        QLabel *lblCurrent = new QLabel(this);
        QLabel *lblSlideTo = new QLabel(this);
        lblCurrent->resize(widget(iCIndex)->size());
        lblSlideTo->resize(widget(slideTo)->size());
        lblCurrent->show(); lblSlideTo->show();
        
        lblCurrent->setPixmap(pmCurrent);
        lblSlideTo->setPixmap(pmSlideTo);
        lblCurrent->raise();     lblSlideTo->raise();
    
        lblCurrent->move(0,0);
        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, [=]{
           setCurrentIndex(iNext);
           widget(iNow)->hide();
           widget(iNow)->move(pNow);
           bActive = false;
           emit AnimationFinished();
        });
        anGroup->start();
    

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

    ui->cStackedMain->setStyleSheet("cStackedWidget{background-color:white;}");
    

    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

    centralWidget->setStyleSheet{background-color:white;}
    

    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;
        opt.init(this);
        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!?


    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


    Q: What's that?
    A: It's blue light.
    Q: What does it do?
    A: It turns blue.

    M V 2 Replies Last reply 10 Mar 2017, 13:58
    0
    • J J.Hilk
      10 Mar 2017, 13:44

      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());
          widget(iCIndex)->render(&pmCurrent);
          QPixmap pmSlideTo = QPixmap(widget(slideTo)->size());
          widget(slideTo)->render(&pmSlideTo);
      
          QLabel *lblCurrent = new QLabel(this);
          QLabel *lblSlideTo = new QLabel(this);
          lblCurrent->resize(widget(iCIndex)->size());
          lblSlideTo->resize(widget(slideTo)->size());
          lblCurrent->show(); lblSlideTo->show();
          
          lblCurrent->setPixmap(pmCurrent);
          lblSlideTo->setPixmap(pmSlideTo);
          lblCurrent->raise();     lblSlideTo->raise();
      
          lblCurrent->move(0,0);
          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, [=]{
             setCurrentIndex(iNext);
             widget(iNow)->hide();
             widget(iNow)->move(pNow);
             bActive = false;
             emit AnimationFinished();
          });
          anGroup->start();
      

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

      ui->cStackedMain->setStyleSheet("cStackedWidget{background-color:white;}");
      

      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

      centralWidget->setStyleSheet{background-color:white;}
      

      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;
          opt.init(this);
          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!?

      M Offline
      M Offline
      mrjj
      Lifetime Qt Champion
      wrote on 10 Mar 2017, 13:58 last edited by
      #2

      @J.Hilk

      Hi
      I think the issue is just who is parent ?
      The stylesheet will affect children so if it works with the custom widget when
      centralWidget->setStyleSheet{background-color:white;}
      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 :)

      1 Reply Last reply
      3
      • J J.Hilk
        10 Mar 2017, 13:44

        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());
            widget(iCIndex)->render(&pmCurrent);
            QPixmap pmSlideTo = QPixmap(widget(slideTo)->size());
            widget(slideTo)->render(&pmSlideTo);
        
            QLabel *lblCurrent = new QLabel(this);
            QLabel *lblSlideTo = new QLabel(this);
            lblCurrent->resize(widget(iCIndex)->size());
            lblSlideTo->resize(widget(slideTo)->size());
            lblCurrent->show(); lblSlideTo->show();
            
            lblCurrent->setPixmap(pmCurrent);
            lblSlideTo->setPixmap(pmSlideTo);
            lblCurrent->raise();     lblSlideTo->raise();
        
            lblCurrent->move(0,0);
            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, [=]{
               setCurrentIndex(iNext);
               widget(iNow)->hide();
               widget(iNow)->move(pNow);
               bActive = false;
               emit AnimationFinished();
            });
            anGroup->start();
        

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

        ui->cStackedMain->setStyleSheet("cStackedWidget{background-color:white;}");
        

        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

        centralWidget->setStyleSheet{background-color:white;}
        

        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;
            opt.init(this);
            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!?

        V Offline
        V Offline
        VRonin
        wrote on 10 Mar 2017, 14:19 last edited by
        #3

        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 http://doc.qt.io/qt-5/stylesheet-syntax.html#selector-types

        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

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        J 1 Reply Last reply 13 Mar 2017, 06:10
        3
        • V VRonin
          10 Mar 2017, 14:19

          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 http://doc.qt.io/qt-5/stylesheet-syntax.html#selector-types

          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

          J Offline
          J Offline
          J.Hilk
          Moderators
          wrote on 13 Mar 2017, 06:10 last edited by
          #4

          @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:

          this->setStyleSheet("QMainWindow{background-color:white;}\
                                  cStackedWidget{background-color:red;}\
                                  QLabel{background-color:blue;}");
          

          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:

          this->setStyleSheet("background-color:red;");
          

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

          LineBreak

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

          this:

          this->setStyleSheet("QMainWindow{background-color:white;}\
                                  cStackedWidget{background-color:red;}\
                                  QLabel{background-color:blue;}");
          

          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:

          this->setStyleSheet("QMainWindow{background-color:white;}\
                                  cStackedWidget{background-color:red;}\
                                  QWidget{background-color:red;}\
                                  QLabel{background-color:blue;}");
          

          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?


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          M 1 Reply Last reply 13 Mar 2017, 07:29
          1
          • J J.Hilk
            13 Mar 2017, 06:10

            @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:

            this->setStyleSheet("QMainWindow{background-color:white;}\
                                    cStackedWidget{background-color:red;}\
                                    QLabel{background-color:blue;}");
            

            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:

            this->setStyleSheet("background-color:red;");
            

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

            LineBreak

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

            this:

            this->setStyleSheet("QMainWindow{background-color:white;}\
                                    cStackedWidget{background-color:red;}\
                                    QLabel{background-color:blue;}");
            

            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:

            this->setStyleSheet("QMainWindow{background-color:white;}\
                                    cStackedWidget{background-color:red;}\
                                    QWidget{background-color:red;}\
                                    QLabel{background-color:blue;}");
            

            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?

            M Offline
            M Offline
            mrjj
            Lifetime Qt Champion
            wrote on 13 Mar 2017, 07:29 last edited by
            #5

            @J.Hilk
            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 :)

            1 Reply Last reply
            0
            • J Offline
              J Offline
              J.Hilk
              Moderators
              wrote on 21 Mar 2017, 06:27 last edited by
              #6

              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;}"
                                      "QWidget#LiveStatus{background-color:white;}"
                                      ...
                                      //List of all  QStackedwidget Pages
                                      ...
                                      "QWidget#FanThreshhold{background-color:white;}");
              

              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 !?


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              1 Reply Last reply
              2

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved