能否转换Q_PROPERTY特殊标记?统一Qt属性获取器实现问询
问题描述
我定义了多个共享同一读写函数的属性,代码如下:
Q_PROPERTY(QString name READ readProp WRITE setProp NOTIFY propChanged) Q_PROPERTY(QString description READ readProp WRITE setProp NOTIFY propChanged) ... Q_PROPERTY(QString date READ readProp WRITE setProp NOTIFY propChanged) QString Company::readProp() { QString name = [name | description | date] ??? // 如何在统一获取器里拿到当前访问的属性名称? return getAttr(name).toString(); } // 我还试过这种写法,但不确定是否可行 QString Company::readProp() { QString name = Q_TRASLATION_PROP_NAME return getAttr(name).toString(); }
请问能不能转换Q_PROPERTY的特殊标记?有没有办法借助QMetaObject实现需求?我不想用QQmlPropertyMap(它工作异常),希望能在获取器内部直接拿到当前访问的属性名称。
解决方案
完全可以借助Qt的QMetaObject元对象系统实现需求,但因为多个属性共享同一读写函数时,公共API无法直接区分当前访问的属性,最稳妥的方案是用宏生成包装函数,既避免重复代码,又能精准获取属性名,且不依赖私有API或不稳定的实现。
一、推荐实现:宏生成属性包装函数
这个方案基于Qt公共API,稳定可靠,代码简洁。核心思路是用宏自动生成每个属性的读写包装函数,这些包装函数调用统一的内部逻辑,并传入属性名称。
1. 头文件中定义宏与属性
在Company类的头文件里添加以下代码:
#include <QObject> #include <QString> class Company : public QObject { Q_OBJECT // 宏:自动生成Q_PROPERTY声明和读写包装函数 #define DECLARE_STRING_PROPERTY(PROP_NAME) \ Q_PROPERTY(QString PROP_NAME READ read##PROP_NAME WRITE set##PROP_NAME NOTIFY propChanged) \ QString read##PROP_NAME() { return readPropInternal(QStringLiteral(#PROP_NAME)); } \ void set##PROP_NAME(const QString& value) { setPropInternal(QStringLiteral(#PROP_NAME), value); } // 用宏快速声明所有属性 DECLARE_STRING_PROPERTY(name) DECLARE_STRING_PROPERTY(description) DECLARE_STRING_PROPERTY(date) #undef DECLARE_STRING_PROPERTY // 释放宏,避免影响其他代码 signals: void propChanged(); private: // 统一的内部读逻辑,接收属性名 QString readPropInternal(const QString& propName) { return getAttr(propName).toString(); // 调用你的数据源获取逻辑 } // 统一的内部写逻辑,接收属性名和值 void setPropInternal(const QString& propName, const QString& value) { // 这里实现你的设置逻辑,比如: // setAttr(propName, value); emit propChanged(); } // 假设这是你的数据源访问函数(根据实际情况实现) QVariant getAttr(const QString& name) const; void setAttr(const QString& name, const QVariant& value); };
2. 实现内部逻辑
在Company的cpp文件里实现getAttr、setAttr等业务逻辑即可,所有属性的读写都会路由到统一的内部函数,且能精准拿到当前操作的属性名。
二、关于QMetaObject直接使用的说明
如果一定要尝试在统一的readProp里直接通过QMetaObject获取属性名,只能依赖Qt的私有API(比如解析QMetaCallEvent),但这种方法跨版本兼容性差,容易出现崩溃,不推荐在生产环境使用。
三、关于Q_TRASLATION_PROP_NAME的说明
你提到的Q_TRASLATION_PROP_NAME不是Qt标准宏,应该是自定义标记。如果是要实现属性名国际化,可以在readPropInternal里对属性名做翻译处理,比如:
QString translatedName = tr(propName.toUtf8().constData()); // 用translatedName代替propName调用getAttr
只需确保翻译文件中包含对应的属性名词条即可。
内容的提问来源于stack exchange,提问作者user20973570
相关产品推荐
相关产品推荐

