当我在C++中为 QML 编写新组件时,我使用宏:
Q_PROPERTY(type READ getter WRITE setter NOTIFY signal)
在这里我可能会使用不同的类型s,例如int
或QVariant
.我想知道,我在这里不使用QVariant
是否有任何好处。
引用文档:
如果没有 QVariant,这对 QObject::p roperty(( 和数据库工作等来说将是一个问题。
那么 - 如果我读取或写入 QML 端的属性会发生什么?
我的猜测是,它调用:
QVariant QObject::property(const char *name) const
bool QObject::setProperty(const char *name, const QVariant &value)
这意味着,我的属性,整齐地定义为我的 getter 返回int, dobule, QString, ...
将被包装为QVariant
从 C++ 传输到 QML - 如果我从一开始就将其定义为QVariant
,这个过程将是不必要的。
如果我在 QML 中有一个组件,那么我很可能有一个属性到多个其他属性的绑定,所以阅读经常发生。因此,最好将类型包含在 QVariantQ_PROPERTY
,否则我会将其包装很多次。
在C++方面,我可能会决定是否经常阅读。如果是这样,我将原始数据类型中的值缓冲以在C++内访问,但是在值更改时创建QVariant
,因此对于 QML,没有必要多次创建它。-还是这是自动发生的?QML 对象是否将其所有属性值缓冲为 QVariant?
不,我想你没有。至少如果你把它暴露给QML或从QAbstractListModel
任何类型的子类中使用(数据函数返回的所有值和返回类型都是QVariant
(
我刚刚通过带有断点的调试器运行我的应用程序,以查看Q_PROPERTY
变量会发生什么。刚刚在函数中添加了截取MouseArray onClicked
简单代码:
var p = ExContact.phone;
var e = ExContact.status;
电话QString
,状态qint8
通过断点显示:
- p 未定义
- p 变为
string
- 分配了 p 值
- e 未定义
- e 变为类型
number
- e 值已分配
调用跟踪在视图中很复杂,但我可以看到使用了什么 QVariant 并使用了 QMetaType。
所以看起来任何通过Q_PROPERTY暴露的类型无论如何都会变成 QVariant。
我在QML上做了一些分析和实验,得出了这个答案,我认为这个答案很有可能:
-
实验:向对象添加属性
property var test
,并在C++中分析其元对象。我发现的是:QMetaObject::property()
方法总是返回一个QVariant
,如此方法的签名中所述,但QVariant
的类型始终设置为属性的类型。这意味着property int someInt
产生QVariant::int
,而property var someVar
产生QVariant::QVariant
- 这意味着至少在这里,我们必须解压缩两次值。+1 使用最合适的属性类型! -
实验:在包含
inline QVariant(QVariant &&other) Q_DECL_NOTHROW : d(other.d)
和inline QVariant &operator=(QVariant &&other) Q_DECL_NOTHROW
的行处将断点添加到QVariant
(QtCore/qvariant.h
( 的源文件中,我发现当我在 QML 中更改QVariant
的值时可能会调用断点。
在 QML 中,我添加了一个Button
,它在单击时增加了其x
位置。
不出所料,每当我单击按钮时,都会重复调用这两行。不幸的是,我错过了洞察力,QVariant
在哪里改变了,以及其中一个是否确实是我们该职位的财产。但是,我不认为Qt会在后端的某个地方有大量QVariant
,所以我认为我的假设很可能是正确的,并且在QML端,属性作为QVariant处理。
带回家的消息:尽管 QML 中的属性是按
QVariant
处理的,但使用更好的拟合类型声明属性是有益的,否则结果不是QVariant::int
,而是QVariant::QVariant::int
。
在我的实验中,我没有发现QJSValues
飞来飞去的痕迹,在有property var ...
时,我不会惊讶地发现而不是QVariant::QVariant