Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Uncknowed Delay in Fade in/ou animation with QPropertyAnimation



  • Hi,

    I'm using QPropertyAnimation to fad in/out two image in the beginig of my App, the images are in Qlabel, where Qlabel are in .../QGraphicsView . The objective is to fade in/out with the first picture, then the seconde picture, there is my code :

        //I have summarized the relevant part of my code
        m_logosLabel1 = new QLabel();
        QPixmap logo(":/images/images/img1.png");
        m_logosLabel1->setPixmap(logo);
        proxy_img1 = new QGraphicsProxyWidget();
        proxy_img1 ->setWidget(m_logosLabel1);
        scene.addItem(proxy_img1 );
    
        m_logosLabel2 = new QLabel();
        QPixmap logo(":/images/images/img2.png");
        m_logosLabel2->setPixmap(logo);
        proxy_img2 = new QGraphicsProxyWidget();
        proxy_img2 ->setWidget(m_logosLabel1);
        scene.addItem(proxy_img2 );
    
        m_logosLabel1 ->setVisible(true);
        m_logosLabel2->setVisible(false);
    
        m_ui->ui_graphicsView->setScene(&scene);
    
        // fade in logo1 for 7s
        QGraphicsOpacityEffect *fadeEffect = new QGraphicsOpacityEffect(this);
        m_ui->ui_graphicsView->setGraphicsEffect(fadeEffect);
        QPropertyAnimation *animLogo = new QPropertyAnimation(fadeEffect,"opacity");
        animLogo->setDuration(7000);
        animLogo->setStartValue(0);
        animLogo->setEndValue(1);
        animLogo->setEasingCurve(QEasingCurve::InBack);
        animLogo>start(QPropertyAnimation::DeleteWhenStopped);
        Delay_MSec(7000);
    
        // fade out logo1 for 7s
        fadeEffect = new QGraphicsOpacityEffect(this);
        m_ui->ui_graphicsView->setGraphicsEffect(fadeEffect);
        animLogo = new QPropertyAnimation(fadeEffect,"opacity");
        animLogo->setDuration(7000);
        animLogo->setStartValue(1);
        animLogo->setEndValue(0);
        animLogo->setEasingCurve(QEasingCurve::OutBack);
        animLogo>start(QPropertyAnimation::DeleteWhenStopped);
        Delay_MSec(7000);
    
        m_logosLabel1 ->setVisible(false);
        m_logosLabel2->setVisible(true);
    
        // fade in logo2 for 7s
        fadeEffect = new QGraphicsOpacityEffect(this);
        m_ui->ui_graphicsView->setGraphicsEffect(fadeEffect);
        animLogo = new QPropertyAnimation(fadeEffect,"opacity");
        animLogo->setDuration(7000);
        animLogo->setStartValue(0);
        animLogo->setEndValue(1);
        animLogo->setEasingCurve(QEasingCurve::InBack);
        animLogo>start(QPropertyAnimation::DeleteWhenStopped);
        Delay_MSec(7000);
    
        // fade out logo2 for 7s
        fadeEffect1 = new QGraphicsOpacityEffect(this);
        m_ui->ui_graphicsView->setGraphicsEffect(fadeEffect1);
        animLogo = new QPropertyAnimation(fadeEffect1,"opacity");
        animLogo->setDuration(7000);
        animLogo->setStartValue(1);
        animLogo->setEndValue(0);
        animLogo->setEasingCurve(QEasingCurve::OutBack);
        animLogo>start(QPropertyAnimation::DeleteWhenStopped);
        Delay_MSec(7000);
    

    My App work fine, the two image are effectively fade in/out one after the other, but there are delay that i can explain every time i begin new animation, no relation with :

      Delay_MSec(7000);
    

    it's look like thar every time, the new animation begin but load maybe in the step :

    animLogo->setStartValue(0);
    

    I really don't know why there is this delay of 3~4second.

    Thanks for help !


  • Lifetime Qt Champion

    Hi
    What is Delay_MSec ?
    Can you show code for it ?
    If it blocks the event loop, QPropertyAnimation might do odd stuff.

    but you tried without it and still have this delay?

    Also, such chained animations is better handled with
    https://doc.qt.io/qt-5/qsequentialanimationgroup.html



  • @mrjj sorry i forget this function :

    void MainWindow::Delay_MSec(unsigned int msec)
        {
              QEventLoop loop; // define a new event loop
              QTimer :: singleShot (msec, & loop, SLOT (quit ())); // create a single timer slot 
              function as an event loop exit function
               loop.exec (); // event loop begins execution, the program will be stuck here until the 
               regular time, this loop is exited
        }
    

    when i remove this function, the animation are not blocked on the actual image, and all my code are fade in/out, i use Delay_MSec to block animation for every image with same value of duration of animation


  • Lifetime Qt Champion

    @jawad_soft

    Hi
    Ok, so its not blocking the event queue as such.
    While QEventLoop is ok as a concept,
    i did have some odd issues with it and QDialogs
    but not sure it's your issue here.

    So they delay is only when you start ?
    It takes 3-4 seconds before it starts fading ?

    I dont see anything that springs to eye.



  • @mrjj ,
    Yes, it's take ~4 seconde when animation start, i don't know if qsequentialanimationgroup can resolve problem ! how i should use it ?



  • @jawad_soft If you want an animation to start after another animation ends then you must use QSequentialAnimationGroup.



  • @eyllanesc i'm trying to use QSequentialAnimationGroup but i don't now how integrate it, can you give me exemple with my animations ?


  • Lifetime Qt Champion

    hi
    Look here
    https://evileg.com/en/post/423/

    Bascially you can just add what you have to the group
    animationGroup->addAnimation(fadeEffect );

    and then use
    https://doc.qt.io/qt-5/qsequentialanimationgroup.html#addPause
    in to add pause in between between



  • @jawad_soft example:

        QGraphicsOpacityEffect *fadeEffect = new QGraphicsOpacityEffect(this);
        m_ui->ui_graphicsView->setGraphicsEffect(fadeEffect);
    
        QPropertyAnimation *anim1 = new QPropertyAnimation(fadeEffect, "opacity");
        anim1->setDuration(7000);
        anim1->setStartValue(0.0);
        anim1->setEndValue(1.0);
        anim1->setEasingCurve(QEasingCurve::InBack);
    
        QPropertyAnimation *anim2 = new QPropertyAnimation(fadeEffect, "opacity");
        anim2->setDuration(7000);
        anim2->setStartValue(1.0);
        anim2->setEndValue(0.0);
        anim2->setEasingCurve(QEasingCurve::OutBack);
    
        QSequentialAnimationGroup *group = new QSequentialAnimationGroup;
        group->addAnimation(anim1);
        group->addAnimation(anim2);
        group->start(QPropertyAnimation::DeleteWhenStopped);
    

    Side note: If you want to display images in QGraphicsView IMO it is better to use a single QGraphicsPixmapItem and then switch QPixmaps when necessary.



  • @eyllanesc said in Uncknowed Delay in Fade in/ou animation with QPropertyAnimation:

    QSequentialAnimationGroup

    @mrjj @eyllanesc ,

    Even with QSequentialAnimationGroup , any animation are blocked with the duration that i chose, it's switch directly to next diplayed think i have in my app, this is why i have used "Delay_MSec(7000);" and also after every "fade out animation " i have to disable one qlabel and activate another !!!

    I never use QGraphicsPixmapItem !!


  • Lifetime Qt Champion

    hi
    but for the same effect as
    Delay_MSec(7000);
    you need to use the addPause

    Did you do that ?



  • @mrjj @eyllanesc

    The addPause doesn't change anything, the animation style none blocking and the delay are always present bettwen each animation!

                        fadeEffect = new QGraphicsOpacityEffect(this);
                        m_ui->ui_graphicsView->setGraphicsEffect(fadeEffect);   
                   
                        // ****************************  logo fade in*******************************
                        animLogo0 = new QPropertyAnimation(fadeEffect,"opacity");
                        animLogo0->setDuration(8000);
                        animLogo0->setStartValue(0.0);
                        animLogo0->setEndValue(1.0);
                        animLogo0->setEasingCurve(QEasingCurve::InBack);
    
    
                        // ****************************  logo fade out*******************************
        
                        animLogo1 = new QPropertyAnimation(fadeEffect,"opacity");
                        animLogo1->setDuration(8000);
                        animLogo1->setStartValue(0.0);
                        animLogo1->setEndValue(1.0);
                        animLogo1->setEasingCurve(QEasingCurve::OutBack);
    
                        // ****************************  logo fade in*******************************
    
                        animLogo2 = new QPropertyAnimation(fadeEffect,"opacity");
                        animLogo2->setDuration(8000);
                        animLogo2->setStartValue(0.0);
                        animLogo2->setEndValue(1.0);
                        animLogo2->setEasingCurve(QEasingCurve::InBack);
    
    
                        // ****************************  logo fade out*******************************
    
                        animLogo3 = new QPropertyAnimation(fadeEffect,"opacity");
                        animLogo3->setDuration(8000);
                        animLogo3->setStartValue(1.0);
                        animLogo3->setEndValue(0);
                        animLogo3->setEasingCurve(QEasingCurve::OutBack);
    
    
                        group->addAnimation(animLogo0);
                        group->addPause(8000);
                        group->addAnimation(animLogo1);
                        group->addPause(8000);
                        group->addAnimation(animLogo2);
                        group->addPause(8000);
                        group->addAnimation(animLogo3);
                        group->addPause(8000);
                        group->start(QPropertyAnimation::DeleteWhenStopped);
    
                       QTextStream(stdout) <<"Animation End"<< endl;
    

    I try also to put all the group->addPause(8000) => group->addPause(100) but that not block anything !
    the " QTextStream(stdout) <<"Animation End"<< endl;" should be executed after the end of all animation, but it's not what happen


  • Lifetime Qt Champion

    @jawad_soft
    Hi
    well it won't block anything (as blocking is bad in event-driven apps)
    but should run them in order.

    Yes "Animation End" will show at once as they
    do not block and its expected to use signal and slot
    for such things.

    Are you saying that addPause Does not add a pause between the animations ?



  • @mrjj ,

    My fault, the addPause add effectively a pause between the animations, but the dealy are alway present !

    I decide to use QAbstractAnimation::finished signal and private slots for every animation to debug the problem and understand exactly when the delay that i want to remove are present, and it's appear that this delay are present in the end of every animation, maybe because i'm increasing/ decresing opacity of the widget and it's take to long time to get opacity(0) maybe. there is any function that make me to dispaly the actual opacity of the widget ?

    Thanks again for your support !


  • Lifetime Qt Champion

    @jawad_soft
    Hi
    Good work.
    There is only the getter for opacity and I'm pretty sure it will report the value you just set.

    if you make the span less 1.0 -> 0.5
    does this pause till happens?



  • yeah i try this trick ! and the opacity of the widget pause on 0.5 i think, but still the delay present ! maybe playing with the opacity of all the widget is not good idea !

    My goal is simple ! fade in/ou two image in the beging of my app, but it's morte complicated that it's appear hahaha

    i creat timer slot that print in the actual opacity every 20Ms, and it's look like good, it's increas/decreas normally


  • Moderators

    There was a similar question recently where someone wanted to animate a gif in a graphics item. Like there - using widgets for animation, much so with their opacity, is a very heavy thing to do.
    A much simpler approach is to make a custom graphics item that just uses painter to draw two images over each other using setOpacity().
    You can use QTimeline to animate it and repaint on its frameChanged signal.

    Here's the custom class that draws gif: https://forum.qt.io/topic/123784/animated-gif-in-qgraphicsscene-qgraphicsview/4
    Should be easy enough to change to drawing two images with a timeline.



  • @Chris-Kawa Thanks for suggestion , i will try this !


Log in to reply