PDA

View Full Version : How to change shape fast



nileshsince1980
17th October 2007, 14:00
Hi,
I am using GraphicsView to display 15,000 > rectangle I want to change the shapes dynamically to Circle, Square or Triangle etc. and vice versa
Which is the fastest way to do this ???

marcel
17th October 2007, 14:12
The most efficient way is to have subclassed QGraphicsItem's.
All items would have multiple QPainterPath members, one for each shape you want them to have.

Then you could iterate through all items in the scene and call a method, let's say switchShape(CustomItem::Circle).
This function would change the shape returned by CustomItem::shape() to the one that represents the circle.

After you finished iterating through all the items you can issue an update on the scene, so the items get updated and the new shapes will be painted.

You can update after you call switchShape for every item, but that introduces extra overhead.

nileshsince1980
17th October 2007, 14:28
Hi
I have tried to override QGraphicsItem's class and changed shape in Paint function.
But after settign the shape for each item I am calling scene's update..but update is taking time reflect the changes.
How to make it fast ??

marcel
17th October 2007, 14:35
Call update only once, after you change the shapes for all items in the scene.

nileshsince1980
17th October 2007, 14:49
I have called only once update..after setting the shape of all items.
but still it is slow
sample code is like this
for (QList<QGraphicsItem *>::iterator it = l.begin(); it != l.end(); ++it)
{
GraphicsItem *item = *it;
item->setShape(ShapeType);
}
scene->update();

//In GraphicsItems class
GraphicsItems::Paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
QPainterPath shape;

painter->setPen(penType);
painter->setBrush(color);

switch(ShapeType)
{
case CircleType:
shape.addPath(circle);
shape.closeSubpath();
break;

case SquareType:
shape.addPath(square);
shape.closeSubpath();
break;

case TriangleType:
shape.addPath(triangle);
shape.closeSubpath();
break;

default:
shape.addPath(circlePath);
shape.closeSubpath();
}

painter->drawPath(shape);
}

marcel
17th October 2007, 14:53
What about setShape? Do you perform any updates there?

nileshsince1980
17th October 2007, 15:01
No In SetShape(..) i just initilaise the type for shape in class data member. and later in Paint(..) draws the shape accordingly.
GraphicsItems::setShape(int type)
{
ShapeType = type;
}

marcel
17th October 2007, 15:10
I think you should cache the shapes and just set them when you paint.
Currently you are constructing the shapes for every paint, and that takes some time for 15k items.

Gopala Krishna
17th October 2007, 15:39
Changing shapes of many items at once incurs lots of changes in bsp indices.

If you are changing shape of many items at one time, the first thing to do should be disble bsp indexing temporarily.

Secondly set the view's update mode to FullScreenUpdateMode(again temporarily)

Thirdly find out what all optimization flags you can set for the view.

Then also if the performance is not ok, start caching the pixmaps.
For eg if most of items look identicle, you can use one pixmap to draw those items that too rapidly.

Also setting QGlWIdget as viewport might have some impact.
To really identify bottlenecks, you should profile your app.

nileshsince1980
18th October 2007, 06:49
I have cached the shapes, All circle, square, triangle varialbe are of type PainterPath, I have created them in GraphicsItem's constructor. & depending upon the selected type of shape I have drawn in Paint function.

What do you mean by caching shapes exactly ???
Please can you more elaborate it ??