能否在QQmlPropertyMap类型的属性中嵌套QQmlPropertyMap以实现QML子属性访问?
能否在QQmlPropertyMap中存入另一个QQmlPropertyMap以实现QML中子属性访问?
问题描述
我目前实现了一个基于QQmlPropertyMap的单例类,无需Q_PROPERTY就能动态创建属性,代码如下:
// myclass.h #include <QQmlEngine> #include <QQmlPropertyMap> class MyClass : public QQmlPropertyMap { public: static MyClass& instance(); ~MyClass() override = default; Q_DISABLE_COPY_MOVE(MyClass) private: explicit MyClass(); }; QObject *qmlMyClassInterface(QQmlEngine *engine, QJSEngine *scriptEngine);
// myclass.cpp #include "myclass.h" #include <QTimer> QObject *qmlMyClassInterface(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(scriptEngine) MyClass *p = &MyClass::instance(); engine->setObjectOwnership(p, QQmlEngine::CppOwnership); return p; } MyClass &MyClass::instance() { static MyClass singleton; return singleton; } MyClass::MyClass() { insert("Test1", "Test 1"); insert("Test2", "Test 2"); QTimer::singleShot(3000, [this]{ insert("Test1", "Update test 1"); insert("Test2", "Update test 2");}); }
// main.cpp #include "myclass.h" qmlRegisterSingletonType<MyClass>("MyClass", 1, 0, "MyClass", qmlMyClassInterface);
// main.qml import MyClass 1.0 title: MyClass.Test1 text: MyClass.Test2
现在我想咨询:是否可以在QQmlPropertyMap类型的属性中存入另一个QQmlPropertyMap对象,从而在QML中实现类似text: MyClass.Test2.SubTest1的子属性访问方式?
解答
当然可以!QQmlPropertyMap支持存储QObject*类型的值,而QQmlPropertyMap本身就是QObject的子类,所以完全可以实现这种嵌套的子属性访问。
具体实现步骤
修改
MyClass构造函数,创建并插入嵌套的QQmlPropertyMap
你需要在构造函数中实例化子级的QQmlPropertyMap,并将其作为值插入到父级MyClass中。同时建议将子对象的父指针设为MyClass,这样父对象销毁时子对象会自动被清理,避免内存泄漏。修改后的
myclass.cpp构造函数如下:MyClass::MyClass() { // 创建子级QQmlPropertyMap,将父对象设为当前MyClass实例 auto subTestMap = new QQmlPropertyMap(this); subTestMap->insert("SubTest1", "Sub Test 1"); subTestMap->insert("SubTest2", "Sub Test 2"); // 插入顶层属性,Test2的值为子级QQmlPropertyMap对象 insert("Test1", "Test 1"); insert("Test2", QVariant::fromValue(subTestMap)); // 3秒后更新顶层属性和子属性 QTimer::singleShot(3000, [this, subTestMap]{ insert("Test1", "Update test 1"); subTestMap->insert("SubTest1", "Updated Sub Test 1"); subTestMap->insert("SubTest2", "Updated Sub Test 2"); }); }在QML中访问子属性
现在你可以直接在QML中通过.链式访问子属性,甚至动态修改它们:import MyClass 1.0 Text { title: MyClass.Test1 text: MyClass.Test2.SubTest1 // 直接访问子属性 Component.onCompleted: { // 动态修改子属性 MyClass.Test2.SubTest2 = "Dynamic Updated Sub Test" } }
关键注意事项
- 对象所有权:如果没有将子
QQmlPropertyMap的父对象设为MyClass,一定要在插入前调用engine->setObjectOwnership(subTestMap, QQmlEngine::CppOwnership),防止QML引擎的垃圾回收机制误销毁子对象。 - 属性更新通知:嵌套的
QQmlPropertyMap同样会自动发出属性变化信号,QML界面会自动响应更新,和顶层属性的行为一致。 - 类型转换:插入子对象时必须用
QVariant::fromValue()将QQmlPropertyMap*转换为QVariant,否则QQmlPropertyMap无法正确识别和存储这个对象。
这样就能完美实现你想要的子属性链式访问啦!
内容的提问来源于stack exchange,提问作者Mait
相关产品推荐
相关产品推荐

