【问题标题】:"Invalid property assignment:.. read-only property" in QmlQml中的“无效的属性分配:..只读属性”
【发布时间】: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);
}

知道我做错了什么吗?

【问题讨论】:

    标签: qt qml


    【解决方案1】:

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

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

    1. 作为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);
      }
      
    2. 作为从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 子类指针的其他列表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 2021-06-30
    • 2016-10-30
    • 2017-03-08
    • 1970-01-01
    相关资源
    最近更新 更多