3

I have my own QGraphicsPixmapItem which consists of a QGraphicsPixmapItem and some additional attributes (like std::string name)

class MyQGraphicsPixmapItem : public QGraphicsPixmapItem { private: std::string name; ... public: MyQGraphicsPixmapItem(); explicit MyQGraphicsPixmapItem(const QPixmap &pixmap, std::string name, QGraphicsItem *parent = nullptr); std::string getname() const; ... }; 

And the constructor is like this :

MyQGraphicsPixmapItem::MyQGraphicsPixmapItem(const QPixmap &pixmap, std::string name, QGraphicsItem *parent) : QGraphicsPixmapItem(pixmap, parent), name(name){ ... } 

Here is the problem : I have a bunch of MyQGraphicsPixmapItem that I add in a QGraphicsScene. But when I use the method QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const, it returns QGraphicsItem* (not MyQGraphicsPixmapItem*). So I suppose that I have to use a down-casting right ? But even after using the down casting like this :

 MyQGraphicsPixmapItem* item = static_cast<MyQGraphicsPixmapItem*>(QGraphicsScene::itemAt(...)); std::cout << item->getName() << std::endl; 

it returns an empty string (like there was no this.name = name; as shown in the constructor).

In conclusion, I create a bunch of MyQGraphicsPixmapItem in a QGraphicsScene with the right name initialization (I tested it with std::cout during the creation of QGraphicsScene) but when I want to randomly select a QGraphicsItem and check what is his name, I use that QGraphicsScene::itemAt that sets back every time the std::string name to empty despite the down-casting. Also, I'm extremely sure that I'm pointing at the right MyQGraphicsPixmapItem with the right arguments (I've done some tests). I was also thinking about implementing the right "itemAt" in my class "MyScene" (which inherits, you guessed it, from "QGraphicsScene") but I would use type_casting again.

PS : Tell me if my question is well asked.

Sincerely yours

7
  • 2
    In general: static_cast may be slightly faster but this is because it won't be checked, dynamic_cast is preferable, and perhaps even more preferable is doc.qt.io/qt-5/qgraphicsitem.html#qgraphicsitem_cast Commented Mar 28, 2019 at 5:22
  • I tried the dynamic and the QGraphicsItem casting and it still doesn't work. I've updated my question by making it simpler. Pleas check it out and tell me if you find something new. Commented Mar 29, 2019 at 2:44
  • I'm a bit puzzled by this.name = name. Firstly why don't you assign it in the initializer list? Secondly... this is a pointer, so I would expect this->name. Commented Mar 29, 2019 at 7:08
  • 1. What do you mean by the initializer list ? The attributes are supposed to be assigned in the constructor. 2. I corrected the mistake. Commented Mar 29, 2019 at 9:12
  • The initializer list is introduced by :. You can do MyQGraphicsPixmapItem::MyQGraphicsPixmapItem(const QPixmap &pixmap, std::string name, QGraphicsItem *parent) : QGraphicsPixmapItem(pixmap, parent), name(name) {} Please see isocpp.org/wiki/faq/ctors#init-lists Commented Mar 29, 2019 at 9:15

1 Answer 1

2

You should be able to use dynamic_cast but Qt provides also its own cast qgraphicsitem_cast which returns item casted to the given type if item is of that type or otherwise 0.

Note from the doc:

To make this function work correctly with custom items, reimplement the type() function for each custom QGraphicsItem subclass.

Example class:

class MyQGraphicsPixmapItem : public QGraphicsPixmapItem { public: ... enum { Type = UserType + 1 }; int type() const override { return Type; } ... }; 

Example test:

MyQGraphicsPixmapItem myItem; qDebug() << &myItem; QGraphicsItem *item = &myItem; MyQGraphicsPixmapItem *castedItem = qgraphicsitem_cast<MyQGraphicsPixmapItem*>(item); if (castedItem) { qDebug() << castedItem; } else { qWarning() << "casting failed"; } 

Update:

QGraphicsScene::itemAt returns the topmost visible item at the specified position, or 0 if there are no items at this position.

If you verified with qgraphicsitem_cast that you successfully casted i.e. it returned pointer and not 0 then you really received your custom item and not some other graphics item. Then it should have name defined and not an empty string if you defined a name for all of your custom items.

To debug this issue further you could use QGraphicsScene::items to list all items on the scene considered visible by QGraphicsScene::itemAt. Do casting in the loop and print out a name of all of your custom items.

One thing that comes to my mind is that this is related to coordinates you are using when calling itemAt. You are e.g. doing your casting when you click with a mouse and then query the scene in the item coordinates and not with the scene coordinates. QGraphicsSceneMouseEvent::scenePos returns the mouse cursor position in scene coordinates. Maybe you are not getting the custom item you think?

Sign up to request clarification or add additional context in comments.

3 Comments

I used your type_casting (including the dynamic one) and it still doesn't work. I also updated the question by making it simpler to understand. Please check it out.
Dear god, something triggered in me when I read "the topmost visible item at the specified position". I actually had a cursor that moves right after I click on the square of my map. That's why the string was empty, the cursor never had his name assigned. I did the last test with the ScenePos (which told me there was no problem). I also printed only the items that had the name assigned (which told me that they exists) and that's why I was confused. Thanks for the help.
@A.Neo I was assuming something like that might be a reason. That's why I wrote Then it should have name defined and not an empty string if you defined a name for all of your custom items. Great to hear you got it solved.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.