对于几个图形对象,我继承自QGraphicsLineItem
,QGraphicsRectItem
等。
class CustomLine : public QGraphicsLineItem{};
class CustomRect : public QGraphicsRectItem{};
这些对象被添加到容器中,该容器是
QGraphicsScene "scene"
的自定义子类,用于显示这些项目并与这些项目进行交互。 this->scene->items()
返回QGraphicItem
的列表:QList<QGraphicsItem* >
我要做的是使每个自定义对象类具有相同的自定义接口方法,例如
setModeX()
。然后我可以做类似的事情:Foreach (BaseItem *item, this->scene->items()){
item->setModeX(...);
}
但是我该如何实现呢?
如果我做一个像
class BaseItem{
public: setModeX(); [...]
private: Mode mode_;
}
并继承
class CustomLine : public QGraphicsLineItem, BaseItem {};
因此,虽然场景仅应包含基于
BaseItem
的项目(不确定是否确实需要此任务),但我首先要检索其2个基类之一(即QGraphicsItem
)的对象列表,并需要进行强制转换它使用其其他基类BaseItem
来使用接口方法。我可能无法在上面的循环中将CustomLine-item强制转换为BaseItem,因为它不了解其他基类。
编辑:
我使用的是MinGW 4.8 32位(g ++)。
我注意到,当我开始foreach循环时,场景中的项目消失了(但尚不知道其原因)
最佳答案
由于scene
是QGraphicsScene
,因此它仅由QGraphicsItem
组成。因此,您不能如代码中所示直接将scene
迭代为BaseItem
。您必须遍历每个QGraphicsItem
。您描述可以先向下转换到CustomLine
然后再向上转换回BaseItem
,但这仅在您知道scene
中的所有项目都是行的情况下才有效。如果scene
包含其他类型的项目,则您的技术将要求您迭代每种项目,直到找到有效的下垂项目,然后将其转换回BaseItem
。
QGraphicsItem
\ BaseItem
QGraphicsLineItem /
\ /
CustomLine
如果Qt库在
QGraphicsItem
上使用了虚拟继承,则可以使用一种简单的解决方案。然后,您只需要对QGraphicsItem
的BaseItem
使用虚拟继承,然后向下转换就可以了。 QGraphicsItem
/ \
QGraphicsLineItem BaseItem
\ /
CustomLineItem
由于Qt不会这样做,因此您可能需要对Qt库进行自定义更改,或者使用自己的转换机制进行编码。
假设您不愿意对Qt库本身进行自定义修改,那么一种方法是在Qt的
QGraphicsItem
和您的BaseItem
之间创建映射。映射可以在BaseItem
的构造函数中完成,并且可以从BaseItem
的析构函数撤消。为了使撤消映射更加有效,您还可以创建从BaseItem
到QGraphicsItem
的链接。class BaseItem {
static std::unordered_map<QGraphicsItem *, BaseItem *> map;
QGraphicsItem *link_;
public:
BaseItem (QGraphicsItem *q) : link_(q) {
//...
map[q] = this;
}
virtual ~BaseItem () {
map.erase(link_);
//...
}
static BaseItem * getBaseItem (QGraphicsItem *q) {
std::unordered_map<QGraphicsItem *, BaseItem *>::iterator i;
if ((i = map.find(q)) == map.end()) return NULL;
return i->second;
}
//...
};
//...
std::unordered_map<QGraphicsItem *, BaseItem *> BaseItem::map;
在派生类中,您只需要将
this
传递给BaseItem
构造函数。class CustomLine : public QGraphicsLineItem, public BaseItem {
public:
CustomLine () : BaseItem(this) {
//...
};
//...
};
然后,循环将使用静态
BaseItem::getBaseItem()
函数将QGraphicsItem
指针转换为BaseItem
指针。因此,由于无法在QGraphicsItem
和BaseItem
之间创建可用的继承关系,因此它们的关系记录在表中。QGraphicsItem <-----------------. link
\ BaseItem <--' map
QGraphicsLineItem /
\ /
CustomLine