views:

78

answers:

1

Since most of the convenience functions of QGraphicsScene and QGraphicsItem (such as items(), collidingItems(), childItems() etc.) return a QList you're forced to do lots of qgraphicsitem_cast or static_cast and QGraphicsItem::Type() checks to get hold of the actual items when you have lots of different type of items in the scene. I thought doing lots of subclass casts were not a desirable coding style, but I guess in this case there are no other viable way, or is there?

QList<QGraphicsItem *> itemsHit = someItem->collidingItems(Qt::IntersectsItemShape);
foreach (QGraphicsItem *item, itemsHit) {
    if (item->type() == QGraphicsEllipseItem::type()) {
        QGraphicsEllipseItem *ellipse = qgraphicsitem_cast<QGraphicsEllipseItem *>(item);
        // do something
    }
    else if (item->type() == MyItemSubclass::type()) {
        MyItemSubClass *myItem = qgraphicsitem_cast<MyItemSubClass *>(item);
        // do something
    }
    // etc
}

The above qgraphicsitem_cast could be replaced by static_cast since correct type is already verified. When doing lots of these all the time (very dynamic scene), will the numerous casting affect performance beyond the normal if-else evaluation?

A: 

The performance overhead is mostly prepaid; it's the result of the overhead of having the .type() member. It might be efficient to retrieve the item->type() once. You know it doesn't change, but chances are the compiler doesn't.

[edit] Also, if you really have a lot of types, it could be worthwhile to introduce some intermediate types. eg. if (dynamic_cast<MyGraphicsInterMediateType*>(item)) {/* check those types */} else {/* other types */}

MSalters
Ah, you mean fetching it once in the beginning of the foreach block? That is a good point.
kleimola
Yup. Now you're fetching it for every comparison. I think it's a virtual call, and while cheap those are not free. Multiply that by every object in every scene, and you have a lot of cheap calls - no longer so cheap, then.
MSalters