You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在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的子类,所以完全可以实现这种嵌套的子属性访问。

具体实现步骤

  1. 修改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");
        });
    }
    
  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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 15:54:08