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

Posted

技术标签:

【中文标题】Qml中的“无效的属性分配:..只读属性”【英文标题】:"Invalid property assignment:.. read-only property" in Qml 【发布时间】:2014-03-11 01:30:24 【问题描述】:

我正在尝试将 Qml 中的列表属性用于基础 C++ 对象。我希望能够阅读和书写它。 QQmlListProperty 的文档说只实现了 READ 函数,用于读取 写入对象。我收到错误消息:

无效的属性赋值:“字符串”是只读属性

当我尝试运行应用程序时。以下是相关的源文件:

main.cpp

#include <QtGui/QGuiApplication>
#include <QtQml>
#include "qtquick2applicationviewer.h"

#include "A.h"

int main(int argc, char *argv[])

    QGuiApplication app(argc, argv);
    qmlRegisterType<A>("TestQmlComponents", 1, 0, "A");

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/TestQml/main.qml"));
    viewer.showExpanded();

    return app.exec();

main.qml:

import QtQuick 2.0
import TestQmlComponents 1.0

Rectangle 
    width: 360
    height: 360

    A 
        id: a
        string: [
            "a", "b", "c"
        ]
    

    Text 
        text: qsTr("Hello World")
        anchors.centerIn: parent
    
    MouseArea 
        anchors.fill: parent
        onClicked: 
            Qt.quit();
        
    

啊哈:

#ifndef A_H
#define A_H

#include <QObject>
#include <QList>
#include <QString>
#include <QtQml/QQmlListProperty>

class A : public QObject

    Q_OBJECT
    Q_PROPERTY(QQmlListProperty<QString> string READ stringList)

public:
    explicit A(QObject *parent = 0);

    static void addString(QQmlListProperty<QString> *list, QString *str);
    void addString(QString *str);
    static int stringCount(QQmlListProperty<QString> *list);
    int stringCount() const;
    QQmlListProperty<QString> stringList();
    static QString *getString(QQmlListProperty<QString> *list, int ix);
    QString *getString(int ix);

private:
    QList<QString *> _string;
;

#endif // A_H

A.cpp

#include "A.h"

A::A(QObject *parent) :
    QObject(parent)



void A::addString(QQmlListProperty<QString> *list, QString *str)

    A *obj = qobject_cast<A *>(list->object);

    if (obj)
       obj->addString(str);


void A::addString(QString *str)

    _string << str;


int A::stringCount(QQmlListProperty<QString> *list)

    A *obj = qobject_cast<A *>(list->object);

    if (obj)
        return obj->stringCount();

    return 0;


QString *A::getString(int ix)

    return _string.at(ix);


QString *A::getString(QQmlListProperty<QString> *list, int ix)

    A *obj = qobject_cast<A *>(list->object);

    if (obj)
        return obj->getString(ix);

    return NULL;


int A::stringCount() const

    return _string.count();


QQmlListProperty<QString> A::stringList()

    return QQmlListProperty<QString>(this, NULL, addString, stringCount, getString, NULL);

知道我做错了什么吗?

【问题讨论】:

【参考方案1】:

QQmlListProperty 只能用于 QObject 派生对象指针的列表。

由于QStringList 作为数组类型透明地暴露给 javascript,您可以通过两种方式直接暴露这样的属性:

    作为Q_PROPERTY,需要注意的是修改代价高昂,因为检索整个字符串列表,然后修改,然后写回。对于大型列表,这很慢。

    Q_PROPERTY(QStringList strings READ strings WRITE setStrings NOTIFY stringsChanged)
    Q_SIGNAL void stringsChanged(const QStringList &);
    ...
    QStringList strings() const  return m_strings; 
    void setStrings(const QStringList & strings ) 
      m_strings = strings;
      emit stringsChanged(m_strings);
    
    

    作为从Q_INVOKABLE 方法返回的引用:直接访问数据。

    Q_INVOKABLE QStringList & strings()  return m_strings; 
    

【讨论】:

对于QQmlListProperty,我需要一个setter吗?我知道 QDeclarativeListProperty 的限制是列表不能作为一个整体写入,但是 QQmlListProperty 的文档表明这个限制已经解除:“QQmlListProperty 封装了一组函数指针,这些函数指针表示 QML 可以执行的操作集在列表上 - 添加项目、检索项目和清除列表。”所以基本的问题是,如何让 QML 将项目添加到 QQmlListProperty,正如文档所说我应该能够做到的那样? @ScottDeerwester 正如我在答案的第一行中所说:您不能将 QQmlListProperty 与非 QObject 类一起使用。那是你的问题。您将它与 QString 一起使用,它永远不会工作。您的addString“setter”是正确的,您只需将QQmlListProperty 与一个不能一起使用的类一起使用。 好吧,我正在使用 QStringList 作为 QStrings。希望我能够获得与 QQmlListProperty 一起使用的 QObject 子类指针的其他列表。

以上是关于Qml中的“无效的属性分配:..只读属性”的主要内容,如果未能解决你的问题,请参考以下文章

PySide2 + QML:QApplication:通过了无效的样式覆盖,忽略它

QML ProgressBar 无效的属性名称“样式”

Qml QtQuick2'无效的属性名称“样式”(M16)' [重复]

QML QtCreator 使用无效代码重新格式化组件类型的属性

当我尝试播放不在 qrc 中的媒体文件时,出现错误“尝试播放无效的 Qt 资源”

在qml映射的位移/缩放稳定后启动filterAcceptsRow