Problem with QGraphicsView performance
Hello,
I have a QGraphicsScene (800X300, 96pp) and I'm having performance problems when I try to implement a background image in a QGraphisScene.
There are not so many items, about ten. But it's really slow. Actually, it's going slower and slower. When the application is running about half minute it takes abut two seconds to react.
My first approach was:
Code:
//scene_test is just 20KB
pPixScene->setPos(-78, -113);
pPixScene = 0;
Second approach:
Code:
brsh.
setTexture(QPixmap(":/Scenes/Scene1/scene_test"));
this->setBackgroundBrush(brsh);
This is even worse, and if I try "m_pView->setCacheMode(QGraphicsView::CacheBackground);" it's definitly impossible.
I think I've tried all the optimization possibilities... for instance:
Code:
m_pView->setContextMenuPolicy(Qt::NoContextMenu);
m_pView
->setOptimizationFlags
(QGraphicsView::DontSavePainterState |
m_pView
->setViewportUpdateMode
(QGraphicsView::NoViewportUpdate/*QGraphicsView::SmartViewportUpdate*/);
//The updates are called manually. As showed in the next piece of code
m_pView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_pView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
I'm controlling the framerate with the next code. But it only fails when I add the background.
Code:
void CGameEngine::renderTimer()
{
m_timer.start();
renderElements();
//Control the updates manually
m_pCurrentScene->update();
qDebug() << m_timer.elapsed();
int iElapsed = 40-m_timer.elapsed(); //20 == 50 fps
if(iElapsed > 0){
QTimer::singleShot(iElapsed,
this,
SLOT(renderTimer
()));
}
else
{
qDebug() << "Performance ERROR: " << iElapsed << " ms!!!!!!!";
renderTimer();
}
}
what I don't understand is why this happens, it takes 2 or 3msec to execute all the code of each frame. Why can it be appearing so slow when I add the background?
Any idea? thanks!
Re: Problem with QGraphicsView performance
Profile your application and see where the slowdown occurs. Right now you are just guessing, especially that calling update() doesn't redraw your scene but only schedules a redraw. Your redrawing routine (renderTimer()) is probably killing performance of your application.
Re: Problem with QGraphicsView performance
With only three graphics items (one of them, the big pixmap) it's slowing down. With almost two hundred and no big pixmap it goes fine, that's why I think the big pixmap is the problem.
I knew the problem of the "update" call. But the other option I thought is to call "drawItems" instead. Can I do it in a different manner?
Re: Problem with QGraphicsView performance
Well, I can only say "thanks". (actually I want to say it three hundred times :P) Now is going better and I'll try to improve it even more with some "tip and tricks" shown in this video.
QGraphicsView in depth
But, on the other hand, I would like to control when the paint is produced (that's why that update()). I can still do it by setting variables in the paint method... but I would like to ask if it's a good idea or I should let Qt go.
Re: Problem with QGraphicsView performance
Your renderTime() method is all wrong. I can't stress it more. I don't know how you measure "slower" and "faster" but if it is based on what your renderTime() method outputs then it is completely useless as it measures the time needed to place an event into the event queue which has nothing to do with redrawing your view. If you want to measure how long it takes for your application to draw your scene then probably the easiest way to do it is this:
Code:
QElapsedTimer timer;
timer.start();
scene->render(&px); // or similar
qDebug() << timer.elapsed();
Re: Problem with QGraphicsView performance
I think you are not understanding why do I need that function. The general idea was to render and paint all the items on the screen each 40 msecs. Now I know this is not true with my code because update() does not paint, just says "calculate and paint whenever you can". I thought the program would stop its executing until the drawing was finished.
Fortunatly, something failed and I can fix the error.
On the oher hand, I still need to know how many miliseconds does the render take. That's why that function is still important.
It seems to work fine removing the update, what I'm planning now is to set a semaphore in the paint method and only allow the painting one time each 40 miliseconds. But I think I should let all the painting stuff to Qt.