当我已经初始化指针属性时,如何将QGraphicsItem向下转换为创建的类?

问题描述 投票:1回答:1

我有自己的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;一样)。

总之,我在MyQGraphicsPixmapItem创建了一堆QGraphicsScene与正确的name初始化(我在std::cout创建期间用QGraphicsScene测试它)但当我想随机选择一个QGraphicsItem并检查他的名字是什么时,我使用那个QGraphicsScene::itemAt那个每次std::string name倒空,尽管进行了挫折,但是每次都会回来。另外,我非常肯定我用正确的论点指向正确的MyQGraphicsPixmapItem(我做了一些测试)。我也在考虑在我的类“MyScene”(它从“QGraphicsScene”继承,你猜对了)中实现正确的“itemAt”,但我会再次使用type_casting。

PS:如果我的问题得到充分询问,请告诉我。

您忠诚的

c++ qt casting
1个回答
1
投票

您应该能够使用dynamic_cast,但Qt也提供了自己的强制qgraphicsitem_cast,如果item属于该类型,则返回给定类型的项目,否则为0。

来自doc的说明:

要使此功能与自定义项一起正常工作,请为每个自定义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返回场景坐标中的鼠标光标位置。也许你没有得到你认为的自定义项目?

© www.soinside.com 2019 - 2024. All rights reserved.