PDA

View Full Version : qgraphicsitem_cast cannot convert seft-defined types



Seishin
9th May 2013, 15:32
I have a class inherits QGraphicsRectItem with type function

int RectItem::type() const
{
return UserType + 1;
}
But when I try to coverting a QGraphicsItem pointer to RectItem pointer, the qgraphicsitem_cast returns null.

QList<QGraphicsItem *> items = scene()->selectedItems();
for(int i=0; i<items.size(); i++){
if(items[i]->type() == UserType + 1)
RectItem*rectItem = qgraphicsitem_cast<RectItem*>(items[i]);
Here rectItem is null. However if I change the cast to dynamic_cast, the convertion will be successful.

QList<QGraphicsItem *> items = scene()->selectedItems();
for(int i=0; i<items.size(); i++){
if(items[i]->type() == UserType + 1){
RectItem*rectItem = dynamic_cast<RectItem*>(items[i]);
Here rectItem is the real RectItem selected.

Anyone knows why qgraphicsitem_cast is not working?
Thanks in advance.

Santosh Reddy
10th May 2013, 10:04
Implement it this way


class RectItem : public QGraphicsItem
{
...
public:
...
enum { Type = UserType + 1 };

int type() const
{
return Type;
}
...
};

Seishin
10th May 2013, 13:14
I tried to use class enum and global enum, but they work the same as without using enum—— type checking returns true, but qgraphicsitem_cast returns null.

Santosh Reddy
10th May 2013, 13:49
Here is an example, it works perfectly, if it still does not work for you, please post a minimum compilable code



#include <QtGui>

class RectItem : public QGraphicsItem
{
public:
explicit RectItem(QGraphicsItem *parent = 0, QGraphicsScene *scene = 0)
: QGraphicsItem(parent, scene) { }

enum { Type = UserType + 1 };

int type() const { return Type; }

QRectF boundingRect() const { return QRectF(); }

void paint(QPainter */*painter*/, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/ = 0) {}
};

int main(int /*argc*/, char **/*argv*/)
{
RectItem rectItem;
QGraphicsItem * item = &rectItem;

qDebug() << "1." << &rectItem;
qDebug() << "2." << qgraphicsitem_cast<RectItem*>(item);

return 0;
}


Output:
1. QGraphicsItem (this = 0x22feec , parent = 0x0 , pos = QPointF(0, 0) , z = 0 , flags = ( ) )
2. QGraphicsItem (this = 0x22feec , parent = 0x0 , pos = QPointF(0, 0) , z = 0 , flags = ( ) )

Seishin
10th May 2013, 14:28
The code you gave is working for me, too. Maybe the reason is you are inheriting from QGraphicsItem but not QGraphicsRectItem.
Here is the code not working.

graphicsItem.h

#include <QtGui>

class RectItem : public QGraphicsRectItem
{
public:
RectItem(QGraphicsItem * parent = 0);
RectItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem * parent = 0);

enum {RectType = QGraphicsRectItem::UserType + 1};
int type() const;
};

graphicsItem.cpp

#include "graphicsItem.h"

RectItem::RectItem(QGraphicsItem * parent)
: QGraphicsRectItem(parent){}

RectItem::RectItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem * parent)
: QGraphicsRectItem(x, y, width, height, parent){}

int RectItem::type() const {return RectType; }
main.cpp

#include "graphicsItem.h"
int main()
{
RectItem rectItem;
QGraphicsItem * item = &rectItem;

if(qgraphicsitem_cast<RectItem*>(item) == NULL)
qDebug() << "qgraphicsitem_cast Failed";
else
qDebug() << "qgraphicsitem_cast Success";

if(dynamic_cast<RectItem*>(item) == NULL)
qDebug() << "dynamic_cast Failed";
else
qDebug() << "dynamic_cast Success";

return 0;
}

Result:
qgraphicsitem_cast Failed
dynamic_cast Success

Santosh Reddy
10th May 2013, 15:33
Ahh, I see your problem, In QGraphicsRectItem class type() function is no more virtual, so inherting from QGraphicsRectItem, and re-implementing type() function is a mear function override in derived class, and is no more polymorphic (virtual) function.

There are two ways to solve, see which one will fit your requirement.

1. Inherit directy from QGraphicsItem, and reimplement type(), and you know what to do then.
2. Inherit from QGraphicsRectItem, and don't implement type(), and offcourse you can use only dynamic_cast<> (qgraphicsitem_cast will not work )

Seishin
10th May 2013, 16:06
Thanks a lot. Actually I think I can still implement type() to override the type() function of QGraphicsRectItem. This may help if I have multiple children classes like RectItem1, RectItem2, etc.

Santosh Reddy
13th May 2013, 14:34
Ahh, I see your problem, In QGraphicsRectItem class type() function is no more virtual, so inherting from QGraphicsRectItem, and re-implementing type() function is a mear function override in derived class, and is no more polymorphic (virtual) function.
This is not correct, I am sorry for the inconvenience caused.

The real reason your code is not wokring is that the enum name is supposed to be "Type" (not "RectType"). Modify you code like this


#include <QtGui>

class RectItem : public QGraphicsRectItem
{
public:
RectItem(QGraphicsItem * parent = 0);
RectItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem * parent = 0);

//enum {RectType = QGraphicsRectItem::UserType + 1};
enum {Type = QGraphicsRectItem::UserType + 1};
int type() const;
};

RectItem::RectItem(QGraphicsItem * parent)
: QGraphicsRectItem(parent){}

RectItem::RectItem(qreal x, qreal y, qreal width, qreal height, QGraphicsItem * parent)
: QGraphicsRectItem(x, y, width, height, parent){}

//int RectItem::type() const {return RectType; }
int RectItem::type() const {return Type; }