[Moved] determing subclass of QGraphicsItem
-
hello,
I have created two subclasses of QGraphicsItem:
- GraphicsItemShield
- GraphicsItemBullet
I have the following loop
@
foreach (QGraphicsItem *item, itemlist) {
// ...
}
@and I like to know of the item is a GraphicsItemShield or a GraphicsItemBullet...
If have tried:
@
if (item->type() == GraphicsItemShield::Type) {
// ...
}
@but it doesn't work :-(
Any idea?
Thanks for your support.
Kind regards,
David DC -
Can you show more code please? What you've shown should work if all other is ok.
-
Hi,
I will paste the advance function of the GraphicsItemBullet below...
What I try to do (to learn the Graphics of Qt) is to show one moving 'shield' en two moving 'bullets'.
In case the bullet hits the shield, the bullet should turn.
In case the bullet hits another bullet, a new bullet will be created
(I will have to implement a limit of number of bullets to avoid an overflow)@
// implement protected functionsvoid GraphicsItemBullet::advance(int phase)
{
if (!phase) return;// turn in case to close to the border QRectF r = boundingRect(); QPointF mypoint(pos()); if (mypoint.x() > (500-r.width())) directionX = -1; if (mypoint.x() < 1) directionX = 1; if (mypoint.y() > (500-r.height())) directionY = -1; if (mypoint.y() < 1) directionY = 1; // turn to avoid collision with shield // and create a new bullet in case two bullets have collision QList<QGraphicsItem *> itemlist = scene()->items(); foreach (QGraphicsItem *item, itemlist) { if (item == this) continue; if (item->type() == GraphicsItemShield::Type) { QPointF checkpoint(item->pos()); if ((mypoint.x() > checkpoint.x() - 30) && (mypoint.x() < checkpoint.x() + 30) && (mypoint.y() > checkpoint.y() - 30) && (mypoint.y() < checkpoint.y() + 30)) { directionX = directionX * -1; directionY = directionY * -1; } } // if type = GraphicsItemShield if (item->type() == GraphicsItemBullet::Type) { QPointF checkpoint(item->pos()); if ((mypoint.x() == checkpoint.x()) && (mypoint.y() == checkpoint.y()) ) { GraphicsItemBullet *bullet = new GraphicsItemBullet; bullet->setPos(5, 5); scene()->addItem(bullet); } } // if type = GraphicsItemBullet } // for each... // move setPos(mapToParent(1 * directionX, 1 * directionY));
}
@
-
one thing you can do is to do a qobject_cast
@foreach (QGraphicsItem item, itemlist) {
// ...
if(qobject_cast<GraphicsItemShield>(item)) {
// item is GraphicsItemShield type
} else if(qobject_cast<GraphicsItemBullet*>(item) {
// item is GraphicsItemBullet type
}
}
@ -
qgraphicsitem_cast fits here better. These items can be derived from QGraphicsItem, not QGraphicsObject. In this case qobject_cast will not work.
daviddc, can you show headers with these classes and their type() methods?
-
Change qobject_cast on static_cast
@
foreach (QGraphicsItem item, itemlist) {
// ...
if(static_cast<GraphicsItemShield>(item)) {
// item is GraphicsItemShield type
} else if(static_cast<GraphicsItemBullet*>(item) {
// item is GraphicsItemBullet type
}
}
@
With type() you can make like this, implement common enum
@
enum { ShieldType = QGraphicsItem::UserType + 1,
BulletType };
@
In class GraphicsItemShield reimplement func
@int GraphicsItemShield::type () const { return ShieldType; }@
In class GraphicsItemBullet reimplement func
@int GraphicsItemBullet::type () const { return BulletType; }@and in your code
@
//...
// turn to avoid collision with shield
// and create a new bullet in case two bullets have collision
QList<QGraphicsItem *> itemlist = scene()->items();
foreach (QGraphicsItem *item, itemlist) {
if (item == this) continue;
switch (item->type())
{
case ShieldType: //do smth
break;
case BulletType: //do another smth
break;
}
//...
}
@
swith gives you more scalable code (because if you, for example, want MagicBulletItem :-) just add another case) -
@
enum { ShieldType = QGraphicsItem::UserType + 1,
BulletType };
@You didn't set BulletType like you did with ShieldType
-
enum do it automatic (he iterate BulletType him self using the previous value, BulletType = ShieldType + 1 and so on)
-
Adding enum with single value in each class will be better.
-
[quote author="Denis Kormalev" date="1307294343"]Adding enum with single value in each class will be better.[/quote]
of course, but in this case programmer must watch the iteration he did. He can mistake and did like this
@
int GraphicsItemShield::type () const
{
return QGraphicsItem::UserType + 1;
}
@@
int GraphicsItemBullet::type () const
{
return QGraphicsItem::UserType + 1;
}
@
Update: and if you want to add another class you just add ClassNameType to enum and return this in new class
Sorry if I undestood you wrong -
Hi,
Thanks for your feedback
I'm rather late home from work
I will give it a try tomorrow and let you know :)David DC
-
Hi,
I have Holiday and found some time to try out your advice.
It works fine with enum type.
@
enum { ShieldType = QGraphicsItem::UserType + 1, BulletType };
@thanks for your support.
Kind regards,
David DC