当我初始化了指针属性 allready 时,如何将 QGraphicsItem 向下投射到创建的类?



我有自己的QGraphicsPixmapItem,它由QGraphicsPixmapItem和一些附加属性(如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;
...
};

构造函数是这样的:

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

问题是:我有一堆MyQGraphicsPixmapItem我添加到QGraphicsScene中。但是当我使用方法QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const时,它返回QGraphicsItem*(而不是MyQGraphicsPixmapItem*)。所以我想我必须使用向下投射的权利?但即使在像这样使用羽绒铸造之后:

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

它返回一个空字符串(就像构造函数中所示没有this.name = name;一样)。

总之,我在具有正确name初始化的QGraphicsScene中创建一堆MyQGraphicsPixmapItem(我在创建QGraphicsScene期间用std::cout对其进行了测试),但是当我想随机选择一个QGraphicsItem并检查他的名字时,我使用该QGraphicsScene::itemAt,尽管进行了向下投射,但每次std::string name清空时都会向后退。 另外,我非常确定我用正确的论点指向正确的MyQGraphicsPixmapItem(我已经做了一些测试)。 我也在考虑在我的类"MyScene"中实现正确的"itemAt"(你猜对了,它继承了"QGraphicsScene"),但我会再次使用type_casting。

PS :告诉我我的问题是否被问得很好。

真诚的你

你应该能够使用dynamic_cast但Qt也提供了自己的强制转换qgraphicsitem_cast如果项目是该类型或0,则返回转换为给定类型的项目。

文档说明:

若要使此函数与自定义项正常工作,请重新实现 每个自定义 QGraphicsItem 子类的 type() 函数。

示例类:

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

示例测试:

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

更新:

QGraphicsScene::itemAt 返回指定位置最顶层的可见项,如果此位置没有项,则返回 0。

如果您用qgraphicsitem_cast验证您成功铸造,即它返回指针而不是 0,那么您确实收到了您的自定义项目,而不是其他图形项目。然后,如果您为所有自定义项定义了名称,则它应该定义名称而不是空字符串。

要进一步调试此问题,您可以使用 QGraphicsScene::items 列出场景中QGraphicsScene::itemAt认为可见的所有项目。在循环中执行强制转换并打印出所有自定义项的名称。

我想到的一件事是,这与调用 itemAt 时使用的坐标有关。例如,当您用鼠标单击然后查询项目坐标中的场景而不是场景坐标时,您正在进行铸造。QGraphicsSceneMouseEvent::scenePos 返回鼠标光标在场景坐标中的位置。也许您没有得到您认为的自定义项目?

最新更新