QGraphicsView performance with lots of items
-
Hi ZapB,
I'm trying QGraphicsPathItem to render a lot of points (1M) for a simple plotting app and .... it's not the good way it seems. Perhaps I don't use it well, but just lineTo, in a for loop give poor result when panning, zooming or add new points.
Have you test this aspect ?
What do you think about the best way to achieve fair results ?regards,
michel
-
This posting was split off from "this topic":http://developer.qt.nokia.com/forums/viewthread/4209, because it is a more general question.
-
Can you post some code that reprodices the problem please? I am interested in seeing how you are using QGraphicsPathItem. What I have done in my case is to make my own QGraphicsItem subclass that uses QPainterPath internally. This was not for performance reasons but because I needed to perform some additional coordinate system transformations.
-
Hi,
I don't have the code here but it's quite "brutal" ;)
something like
@
QPainterPath p;
p.moveTo(0, 0);
for(int i=0, i< 1 000 000, i++)
{
x(i) = ...;
y(i) = ...;
p.lineTo(x(i), y(i));
}my_scene->addPath(p);
@So, OK, it's quite stupid to ask drawing millions point on a screen. I just try to understand how to plot a big vector of data ;)
I've test with a "big" image item, and here the magic is coded. I mean, I put in the scene a 65000*4000 pixels image and gui keep responsive, all the cache/decimation and so on stuff is "transparent" for developer.
I thought that the same logic was available for Path. Ok I give a lot of points, but internally, the framework could select the parts to draw.
Perhaps it's the case! I just don't use the good maner.
I'd like to understand what I can/cannot do with painting in Qt before doing my code, filtering in paint event what to do ;)
If I'm lazy... yes! It gives me more time to work on other subject :)
I hope that my english can be understood, and thanks for your interest,
regards,
michel
-
[quote author="Michel Pacilli" date="1308571608"]
@
QPainterPath p;
p.moveTo(0, 0);
for(int i=0, i< 1 000 000, i++)
{
x(i) = ...;
y(i) = ...;
p.lineTo(x(i), y(i));
}my_scene->addPath(p);
@
michel [/quote]OK. Well the first thing to try is to enable caching on the path item. This basically turns the item into a pixmap and so enables the same kidn of performance you see with your other large pixmap type items.
To do this change your code to somethign like this:
@
QPainterPath p;
p.moveTo(0, 0);
for(int i=0, i< 1 000 000, i++)
{
x(i) = ...;
y(i) = ...;
p.lineTo(x(i), y(i));
}QGraphicsPathItem* pathItem = my_scene->addPath(p);
pathItem->setCacheMode( QGraphicsItem::DeviceCoordinateCache );
@If you need to also handle scaling and rotation of the item then you may be better off setting it to QGraphicsItem:ItemCoordinateCache. Take a look at the docs for more info on this.
HTH
-
Yes it's better, but not enough ;)
I play with cache type and don't find a good cook
ItemCoordinateCache is quite strange ! I scale the item to the QSize of the cache, so we need to strech the item in order to have the same surface occupied. Perhaps a way to deal with the problem is to change cache size when scene scale change .... but well, it seems that implement filter in draw event is quite simpler.If you have some ideas/experiences about that problem, I will test ;)
best regards
-
Can you post a small compilable example please? Best approach will be to profile it (e.g. use valgrind) to see what is taking the time when scrolling. The above caching should have given similar performance to using a pixmap.
I am not quite clear on what type of transformations you allow and which need to be fast. A simple example would help me to help you (if I can).
-
sure, thanks for help :)
I just create a mainwindow project in creator, and add a graphicsview.
on action "draw" added in the menu I slot that simple code:@
void MainWindow::on_actionDraw_triggered()
{
QGraphicsPathItem* p = NULL;
QPainterPath pa;QGraphicsScene* scene = new QGraphicsScene(); ui->graphicsView->setScene(scene); ui->graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); //ui->graphicsView->setRenderHint(QPainter::HighQualityAntialiasing); ui->graphicsView->setInteractive(true); ui->graphicsView->setDragMode(QGraphicsView::ScrollHandDrag); scene->setSceneRect(0, 0, 1000, 1000); pa.moveTo(0, 0); qreal n = 1e6; for(qreal i = 0; i < n; i = i + 1.0) { qreal x = i/n*1000.0; qreal y = 500.0 * (cos(2.0*M_PI*x/100.0)) + 500.0; pa.lineTo(x, y); } p = scene->addPath(pa, QPen()); p->setCacheMode( QGraphicsItem::DeviceCoordinateCache ); //p->setCacheMode( QGraphicsItem::ItemCoordinateCache, QSize(1024, 768) );
}
@Do you think that with the good configuration (cache, ...) the framework can do all the magic ?
I hope so ;)
-
did you solve this problem? I am facing the same question,I dont know how to deal with it ,please tell me ,thank you