Repainting QWidget with QProperAnimation



  • I have a piece of code that initializes an instance of QWidget, puts it inside a layout and invokes the animation. All of that is happening in the loop. I've encountered a problem of animation being drawn only after the loop is over, though I need it to paint every iteration. QThread::sleep() , repaint() , update() , QCoreApplication::processEvents() have all failed to give me the solution. Is there a way to prompt the execution of the QProperAnimation inside setChunk() method?`

     for(int p = 0 ; p < 100 ; p++)
                {
    
                    for(int i = 0 ; i < numOfPoints ; i++)
                    {
                        randomTestArray[i] = fMin + (double)rand() * (fMax - fMin) / RAND_MAX;
                    }
                    QCoreApplication::processEvents();
                    eq->setChunk(&randomTestArray[0] , &startArray[0]);
                }
    

  • Qt Champions 2016

    @MadScientist92 said in Repainting QWidget with QProperAnimation:

    setChunk

    Can you also show how u start the animation ?

    I think the main issue is the loop. You will starve the event loop and QAnimations depends on it.
    Even you call processEvents() its not enough for smooth animation.



  • This is setChunk() method : 
    
            QPropertyAnimation *animationLine = new QPropertyAnimation(this , "nline");
            animationLine->setDuration(2000);
            animationLine->setStartValue(QLine(xCoordinateArray[0] + 5 , *(startYArr + 0) , xCoordinateArray[1] , *(startYArr + 1)));
            animationLine->setEndValue(QLine(xCoordinateArray[0] + 5 , 150 - yCoordinateArray[0] , xCoordinateArray[1] ,  150 - yCoordinateArray[1]));
            animationLine->start(QAbstractAnimation::DeleteWhenStopped);
            connect(animationLine , &QPropertyAnimation::valueChanged , [=](){update();});
          QPropertyAnimation *animationLine2 = new QPropertyAnimation(this , "nline2");
            animationLine2->setDuration(2000);
            animationLine2->setStartValue(QLine(xCoordinateArray[1] + 5 , *(startYArr + 1) , xCoordinateArray[2] ,    *(startYArr + 2)));
            animationLine2->setEndValue(QLine( xCoordinateArray[1] + 5 , 150 - yCoordinateArray[1]  ,xCoordinateArray[2] , 150 - yCoordinateArray[2]));
            animationLine2->start(QAbstractAnimation::DeleteWhenStopped);
            connect(animationLine2 , &QPropertyAnimation::valueChanged , [=](){update();});
    ...
    

    and paintEvent() :

    void Equalizer::paintEvent(QPaintEvent *event)
    {
    Q_UNUSED(event);
    
    QRect ellipse(mRect);
    QPainter painter(this);
    painter.setBrush(Qt::red);
    painter.drawEllipse(ellipse);
    
    QRect ellipse2(mRect2);
    painter.setBrush(Qt::red);
    painter.drawEllipse(ellipse2);
    
    QRect ellipse3(mRect3);
    painter.setBrush(Qt::red);
    painter.drawEllipse(ellipse3);
    ....

  • Qt Champions 2016

    @MadScientist92
    It looks ok so I guess its the loop of 100 that does it.
    Even if u call processEvents, then the double loop might block the loop so long that it
    cannot run the animations before later.

    How much is numOfPoints ?



  • @mrjj it's 20. Btw, in this case only the last animation is drawn. I've tried initializing Equalizer object and adding it to the layout upon every iteration and then destroying it, and that leaded to all animations being displayed at the same time.


  • Qt Champions 2016

    @MadScientist92
    Ok, thats not so bad.

    If you only make one ( instead of 100 ), does it work ?



  • I've updated previous comment. It paints only one animation anyway


  • Qt Champions 2016

    @MadScientist92

    Ok, im not sure what could be wrong.

    Is it possible to upload project somewhere and post link here?
    I want to run it.
    Something is going on, i dont see.
    Its clear the loop with 100 kills the event loop ( u need other design)
    but both animations should run when there is only 1.





  • @mrjj What's interesting, is that even if I try just to call this setChunk() method manually for two times in a row, without any loop, it still would paint only one animation.


  • Qt Champions 2016

    @MadScientist92

    ok. sounds. odd. i dont have time before tonight to see if i get same result :)



  • Solved it by creating QTimer) Thanks for your help!


  • Qt Champions 2016

    @MadScientist92
    Ok i was actually thinking about suggesting that to avoid the loop.

    Does it then run in parallel as you want?



  • Yes, it is now painting all the animations I want sequentially . Have to play around with the timing though, but that is still a huge step forward after a week of stupor)



  • @MadScientist92
    Hi, from what I read sofar in this thread, I asume you want to draw a couple lines. In that way that only 1 line is drawn at a time? E.g: line 1 is drawn -> start drawing line2

    I would suggest the following:

    Move all your animations into a list:

    QList<QPropertyAnimation*> animationList;
    
    animationList.append(animation1);
    animationList.append(animation2);
    ...
    animationList.append(animationLast);
    

    That make the following loop:

    for(int i = 0; i < animationList.size()-1; i++){
         connect(animationList[i], &QPropertyAnimation::finished, animationList[i+1], [=]{animationList[i+1]->start();});
    }
    

    This will automatically start the next animation, once the previousone is finsihed. No need for extra QTimer management,

    If you want instead to draw multiple lines simultaneously, I would suggest looking into QParallelAnimationGroup



  • I was attempting to draw equalizer for sound. Therefore, I needed to paint multiple 'states' of it. The problem was that only the last 'state' was drawn, and I wasn't getting a sequence of different animations.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.