C++ 对象属性的 QML 属性

Posted

技术标签:

【中文标题】C++ 对象属性的 QML 属性【英文标题】:QML property of property of C++ object 【发布时间】:2013-10-15 00:30:28 【问题描述】:

我是 QML 新手,在访问 C++ 对象的 property.property 时遇到问题:

C++、频率和电台都是Qt元类型注册对象:

CStation *station = new CStation(...); // QObject
CFrequency *frequency = new CFrequency(..); // QObject
QQmlContext *qmlContext = viewer.rootContext();
qmlContext->setContextProperty("myatcstation", station);
qmlContext->setContextProperty("myfrequency", frequency);

QML:

 RowLayout  ....
        TextField 
            text: myatcstation.toQString(true)
        
    
 ....       text: myfrequency.toQString(true)

这行得通,但是当我写:text: myatcstation.frequency.toQString(true) 我确实得到TypeError: Object [object Object] has no method 'toQString'

frequency 是类CStation 的属性设置为Q_PROPERTY(CFrequency frequency READ getFrequency)

C++ 中的交叉检查有效:

CFrequency test = station->property("frequency").value<CFrequency>();

-- 编辑:弗兰克的回答--

这两个类都是从QObject 派生的,它不是教科书上的,因为它们是可复制的。我知道Identity vs value 的情况。

频率基本上是一个值对象,但我已将其设为基于QObject,因此我可以使用它的属性(请参阅Any chance to use non QObject classes with QML)。在示例中,toStringQ_INVOKABLE,频率在非工作情况下返回 QObject 派生的 CFrequency 对象的副本。

-- 编辑:进一步的发现--

当我将频率属性更改为返回 CFrequency* 而不是 CFrequency 时,它也不起作用。当我得到TypeError: Cannot call method 'toQString' of undefined 时,情况似乎是一样的。 CFrequency 单独工作,但 QML 不理解 myatcstation.frequency 是具有 toString 的频率对象。

【问题讨论】:

【参考方案1】:

CFrequency 不是我假设的 QObject,否则您不会按值而是按指针返回它。要使 `toQString() 可以从 QML 调用,它必须是 Q_INVOKABLE 或插槽,这意味着 CFrequency 也必须是 QObject。

如果一个电台只有一个频率,请考虑将相关信息移动到电台对象中,即将您需要的频率信息作为属性添加到 CStation。

要在频率更改时获取更新,请考虑使用 Q_PROPERTY(QString frequencyAsString READ frequencyAsString NOTIFY frequencyAsStringChanged) 等属性,而不是 toQString()。属性通过属性绑定“内置”了更新机制,而没有好的方法告诉 QML 它应该再次调用 toQString,因为频率发生了变化。

【讨论】:

好提示,在上面添加了一些信息。问题是,如果 CFrequency(这是一个 QObject 按值返回)作为副本返回(即使不希望复制 QObjects),它是否可以工作。【参考方案2】:

我解决了一个类似的问题:

class TopObject : public QObject

  Q_OBJECT
    Q_PROPERTY(ValueObject* theValue ...
  ...


class ValueObject : public QObject

  Q_OBJECT
    Q_PROPERTY(QString value ...
  ...

在主应用程序中:

qRegisterMetaType<ValueObject>("ValueObject");
qmlRegisterType<ValueObject>("com.name.comp", 1, 0, "ValueObject");

...->setContextProperty("topObject", new TopObject());

在qml代码中:

import com.name.comp 1.0

... 
  text: topObject.theValue.value
...

两者都需要,将属性 (ValueObject) 作为指针返回并使用 qmlRegisterType 注册。

另见Exchange Data and Objects between C++ and QML and vice versa

【讨论】:

以上是关于C++ 对象属性的 QML 属性的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中循环读取 QML 对象(CheckBox)属性:总是相同的值

C++ 类以时尚 TypeError 暴露于 QML 错误:对象的属性“...”不是函数

如何从 C++ 中删除属性上的 QML 绑定?

Qml中的“无效的属性分配:..只读属性”

Qt Qml连接到Context属性的QObject属性的信号

Qt Quick - 如何仅通过 c++ 代码与 qml 属性交互