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

Render QGraphicsView into video file problem



  • Hello,

    I'm developing a 2D/3D animation desginer program which user can design animated items on a graphic scene, after designing user needs to be able to convert the animation into a specific video file, for rendering I just run a QTimer with Qt::PreciseTimer key (when animation is playing on the QGraphicsView) and set its interval to 33ms to get 30 shots per second and in its timeout signal I just use GraphicsView->render to get an image of what is displaying on the scene then save it to the file, the problem is that the timer timeout interval isn't accurate especially if I move window or do something else during the conversion process!
    even I moved the timer in to another Thread but it didn't do the trick!

    Min Time: 33  Cur Time:  65 elapsed  64  Max Time: 65
    Min Time: 32  Cur Time:  32 elapsed  31  Max Time: 65
    Min Time: 32  Cur Time:  32 elapsed  32  Max Time: 65
    Min Time: 32  Cur Time:  33 elapsed  32  Max Time: 65
    Min Time: 32  Cur Time:  33 elapsed  33  Max Time: 65
    Min Time: 32  Cur Time:  32 elapsed  31  Max Time: 65
    Min Time: 32  Cur Time:  50 elapsed  49  Max Time: 65
    Min Time: 22  Cur Time:  22 elapsed  22  Max Time: 65
    Min Time: 22  Cur Time:  27 elapsed  27  Max Time: 65
    Min Time: 22  Cur Time:  33 elapsed  32  Max Time: 65
    Min Time: 22  Cur Time:  33 elapsed  32  Max Time: 65
    Min Time: 22  Cur Time:  33 elapsed  32  Max Time: 65
    Min Time: 22  Cur Time:  32 elapsed  32  Max Time: 65
    Min Time: 22  Cur Time:  34 elapsed  32  Max Time: 65
    

    for another method I used a QTimeLine which is set to the animation and by its FrameChanged singnal I supposed to find the exact end time of a frame to take picture, but again the framechange signal isn't accurate too!

    Min Time: 0  Cur Time:  50  Max Time: 50
    Min Time: 0  Cur Time:  32  Max Time: 50
    Min Time: 0  Cur Time:  32  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  34  Max Time: 50
    Min Time: 0  Cur Time:  32  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  25  Max Time: 50
    Min Time: 0  Cur Time:  40  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  35  Max Time: 50
    Min Time: 0  Cur Time:  31  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  35  Max Time: 50
    Min Time: 0  Cur Time:  31  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  32  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    Min Time: 0  Cur Time:  32  Max Time: 50
    Min Time: 0  Cur Time:  33  Max Time: 50
    

    with this problem, when I have a animated graphic item which is moving linearly from left to right of the scene, after converting it to a vide file, when I paly the file I can see that item moves 3 pixels in one frame and it moves 5 pixels in another frame while it should move equal pixels in every frames!!

    I'm using QElapsedTimer to fine elapsed time between every frames timeout,

    what do you think is the problem ? is there any better approch to render a QGraphicsView in a video ?

    and is there any other way to no showing anything on the screen when you just want to render animations into a file ? something like offscreen scene ?

    some piece of codes of the program

    void ZAnimator::onFrameChanged()
    {
       timeta = elapsedTimera->elapsed();
       elapsedTimera->restart();
    
       if (timeta > maxtimeta)
           maxtimeta = timeta;
    
       if (timeta < mintimeta)
           mintimeta = timeta;
    
       qDebug() << "Min Time:" << mintimeta <<" Cur Time: " << timeta << " Max Time:" << maxtimeta;
    
        screenPixmap->fill(Qt::black);
    
        m_curSB->getGV()->render(screenPainter, screenPixmap->rect(),bRect);
    
        *tempImage = screenPixmap->toImage();
    
        imageData.push_back(*tempImage);
    }
    


  • opencv (extra characters to make response longer than 8 characters...lame!)