3

In the function of itemChange, first ,I get the child item that will be added, then I use dynamic_cast cast it to 'MyItem', but the cast always fail.

 QVariant MyItem::itemChange ( GraphicsItemChange change, const QVariant & value )
{

if (change==ItemChildAddedChange)
{
  QGraphicsItem* item=value.value<QGraphicsItem*>();
if (item)
{
     MyItem* myItem=dynamic_cast<MyItem*>(item);//myItem always be NULL,
//although I know the item is 'MyItem' type.
     if (myItem)
      {
       qDebug()<<"successful!";
       }
       }
}
return QGraphicsItem::itemChange(change,value);
}

Thanks very much!

skaffman
  • 398,947
  • 96
  • 818
  • 769
jnblue
  • 269
  • 5
  • 16

2 Answers2

3

Note the comment on itemChange:

Note that the new child might not be fully constructed when this notification is sent; calling pure virtual functions on the child can lead to a crash.

dynamic_cast can also fail if the object is not fully constructed. (I don't quite understand the spec on this, but there are some cases where it will, some where it will not.) If you set the parent after constructing the item, it will work:

#include <QtGui>

class MyGraphicsItem : public QGraphicsRectItem {
public:
  MyGraphicsItem(QGraphicsItem *parent, QGraphicsScene *scene)
    : QGraphicsRectItem(0.0, 0.0, 200.0, 200.0, parent, scene) {
    setBrush(QBrush(Qt::red));
  }
protected:
  QVariant itemChange(GraphicsItemChange change, const QVariant &value) {
    if (change == QGraphicsItem::ItemChildAddedChange) {
      QGraphicsItem* item = value.value<QGraphicsItem*>();
      if (item) {
        MyGraphicsItem* my_item=dynamic_cast<MyGraphicsItem*>(item);
        if (my_item) {
          qDebug() << "successful!";
        }
      }
    }
    return QGraphicsRectItem::itemChange(change, value);
  }
};

int main(int argc, char **argv) {
  QApplication app(argc, argv);

  QGraphicsScene scene;
  MyGraphicsItem *item = new MyGraphicsItem(NULL, &scene);

  // This will work.
  MyGraphicsItem *item2 = new MyGraphicsItem(NULL, &scene);
  item2->setParentItem(item);

//  // This will not work.
//  MyGraphicsItem *item2 = new MyGraphicsItem(item, &scene);

  QGraphicsView view;
  view.setScene(&scene);
  view.show();

  return app.exec();
}
Dave Mateer
  • 17,608
  • 15
  • 96
  • 149
  • 1
    Thanks very much! You are right, it's failed because using 'dynamic_cast' in the constructor..[link](http://stackoverflow.com/questions/6299266/dynamic-cast-of-this-inside-constructor). Because the 'itemChange' will be called in the constructor of QGraphicsItem, and up to that time ,the 'Myitem' hasn't been formed(constructed), so it will be failed. – jnblue Aug 08 '11 at 13:01
0

Try using qgraphicsitem_cast

O.C.
  • 6,711
  • 1
  • 25
  • 26
  • Have you defined a UserType for your class as shown in the example ? – O.C. Aug 08 '11 at 12:58
  • Thank's for you reply, I have tested using 'qgraphicsitem_cast', it failed too. because the 'type()'function using by 'qgraphicsitem_cast' is 'virtual', so according to the qdoc, using 'virtual' function in the 'ItemChildAddChange' and 'ItemChildRemovedChange' is wrong. The answer by Dave is the right thing, thank you very much anyway. – jnblue Aug 08 '11 at 13:10