我有几个QObject
类,可能有QList
个属性,用于存储QObject
派生类的列表:
class Object : public QObject
{
Q_OBJECT
Q_PROPERTY(QList<AnotherQObject*> otherObjects READ otherObjects)
public:
QList<AnotherQObject*> otherObjects() const;
}
QList<AnotherObject*>
当然已在Q_DECLARE_METATYPE
和qRegisterMetaType()
注册。
现在我想用Qt的元对象系统读取这个属性。在我想要阅读列表的那一点上,我只关心(并且知道)列表包含指向对象的指针这一事实,这些指针来自QObject
,但不是确切的类型。
当我将该属性的QVariant
转换为QList<QObject *>
时,该列表为空。
QObject *object = getObjectFromSomeWhere();
const char* propertyName = getPropertyNameFromSomeWhere(); // "otherObjects"
QVariant list = object->property(name);
QList<QObject *> objectList = list.value<QList<QObject *> >(); // empty
QList<AnotherQObject*> anotherObjectList =
static_cast<Object*>(object)->otherObjects() // not empty
是否可以访问此列表?你有其他建议吗?
编辑:虽然我发布了我的解决方案,但我仍然喜欢评论: - )答案 0 :(得分:3)
如果您使用的是Qt 5.2或更高版本,则可以使用QSequentialIterable类,而无需额外模板,修改后的宏和其他注册的开销。
http://qt-project.org/doc/qt-5/qsequentialiterable.html
如果QList<T*>
中存储QVariant
,其中T来自QObject
,则可以从变体中获取QSequentialIterable
个实例,这样您就可以迭代列表中的每个项目为QVariant
。然后,您可以简单地将每个项目的值作为QObject*
获取,然后添加到QList<QObject*>
(确保您测试类型派生自QObject
的假设) :
QList<QObject*> qobjectList;
if (variant.canConvert(QMetaType::QVariantList)) {
QSequentialIterable iterable = variant.value<QSequentialIterable>();
foreach (const QVariant& item, iterable) {
QObject* object = item.value<QObject*>();
if (object) { qobjectList.append(object); }
}
}
答案 1 :(得分:2)
我认为我很简单地解决了这个问题。我创建了一个模板类,可以将包含QVariant
的{{1}}转换为QList<TemplateParameter *>
。
我还有一个单例,它存储QList<QObject *>
,从QMap<int, Converter *>
映射到相应的转换器。
这允许我注册每个类,我想将它存储在属性中,如下所示:
QVariant::userType()
然后我可以转换未知的VariantToObjectListConverter::instance()->registerConverter<AnotherQObject>();
:
QVariants
这是必要的代码:
QVariant list = object->property("otherObjects");
QList<QObject *> objects = VariantToObjectListConverter::instance()->convert(variant);
我现在可以添加一个调用class ConverterBase
{
public:
virtual ~ConverterBase() {}
virtual QList<QObject *> convert(const QVariant &variant) const = 0;
};
template<class Object>
class Converter : public ConverterBase
{
public:
QList<QObject *> convert(const QVariant &variant) const
{
QList<Object *> list = variant.value<QList<Object *> >();
QList<QObject *> result;
Q_FOREACH(Object *object, list) result.append(object);
return result;
}
};
class VariantToObjectListConverter
{
public:
Q_GLOBAL_STATIC(VariantToObjectListConverter, instance)
~VariantToObjectListConverter()
{
QHashIterator<int, ConverterBase *> i(m_converters);
while (i.hasNext()) {
i.next();
delete i.value();
}
}
template<class Object>
void registerConverter()
{
QVariant v = QVariant::fromValue<QList<Object *> >(QList<Object *>());
m_converters.insert(v.userType(), new Converter<Object>());
}
QList<QObject *> convert(const QVariant &variant) const
{
ConverterBase *converter = m_converters.value(variant.userType());
if (!converter)
return QList<QObject *>();
return converter->convert(variant);
}
private:
QHash<int, ConverterBase *> m_converters;
VariantToObjectListConverter() {}
};
,registerConverter()
和Q_DECLARE_METATYPE
的宏,这样用户只需要调用
qRegisterMetaType()