Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

“Read-only property” error when using QQmlListProperty with custom class in QML



  • I am following the "example":http://qt-project.org/doc/qt-5/qtqml-tutorials-extending-chapter6-plugins-example.html to expose a custom type as a QQmlListProperty in QML. At runtime, when initializing the list property, I get the error Invalid property assignment: "overlayImages" is a read-only property.

    This is what I want to do in QML:

    @TestPattern {
    id: pattern

    overlayImages: [
        OverlayImage {
            x: 100
            y: 100
            alpha: 0.1
            source: "../../images/fail.png"
            visible: true
        }
    ]
    

    }@

    Here are my custom type declarations:

    @class TestPatternQuickPrivate;
    class QMLTESTPATTERN_EXPORT TestPatternQuick : public QQuickItem
    {
    Q_OBJECT
    Q_DECLARE_PRIVATE(TestPatternQuick)
    Q_DISABLE_COPY(TestPatternQuick)
    Q_PROPERTY(QQmlListProperty<OverlayImage> overlayImages READ overlayImages)

    public:
        TestPatternQuick(QQuickItem *parent = Q_NULLPTR);
        virtual ~TestPatternQuick();    
        QQmlListProperty<OverlayImage> overlayImages();
    
    private:
        static void appendOverlayImage(QQmlListProperty<OverlayImage> *list, OverlayImage *overlayImage);
        QScopedPointer<TestPatternQuickPrivate> d_ptr; //QScopedPointer guarantees no throw
    };
    
    class OverlayImagePrivate;
    class QMLTESTPATTERN_EXPORT OverlayImage : public QQuickItem
    {
        Q_OBJECT
        Q_DECLARE_PRIVATE(OverlayImage)
        
    public:
        OverlayImage(QQuickItem *parent = Q_NULLPTR);
        OverlayImage(const OverlayImage &other);
        virtual ~OverlayImage();
        OverlayImage &operator=(const OverlayImage &other);
    
    private:
        QScopedPointer<OverlayImagePrivate> d_ptr; //QScopedPointer guarantees no throw
    };@
    

    ...and C++ plugin registration implementation:

    @void QmlTestPatternPlugin::registerTypes(const char *uri)
    {
    qmlRegisterType<TestPatternQuick>(uri, 1 /major/, 0 /minor/, "TestPattern");
    qmlRegisterType<OverlayImage>(uri, 1 /major/, 0 /minor/, "OverlayImage");
    }@

    Can anyone shed light on what I'm still missing?


  • Qt Champions 2017

    You are making the overlay images are read only.

    @Q_PROPERTY(QQmlListProperty<OverlayImage> overlayImages READ overlayImages)@

    You need to add the write function for this. Have look at how to declare Q_PROPERTY with read, write, signals etc.



  • Based on the example, it appears that the QQmlListProperty uses function pointers rather than getter/setter to access the property. I thought this was strange too and not very Qt.


  • Qt Champions 2017

    There is one specific example given in the Qt installation under examples. You can look at. It may give you good pointers for you.

    Qt5.3.1/Examples/Qt-5.3/qml/referenceexamples/properties/birthdayparty*



  • I'm currently running into the very same issue as yiyangfei and I even looked at the example Dheerendra specified. In this "Birthdayparty example":http://doc.qt.io/qt-5/qtqml-referenceexamples-properties-example.html however also no WRITE part for the Q_PROPERTY is specified. And frustratingly the Birthday example compiles and runs whereas my solution complains about the property being read-only. I wonder if it has to do with the way BirthdayParty is instantiated!?



  • I'm currently running into the very same issue as yiyangfei and I even looked at the example Dheerendra specified. In this "Birthdayparty example":http://doc.qt.io/qt-5/qtqml-referenceexamples-properties-example.html however also no WRITE part for the Q_PROPERTY is specified. And frustratingly the Birthday example compiles and runs whereas my solution complains about the property being read-only. I wonder if it has to do with the way BirthdayParty is instantiated!?



  • Ok, I think at least in my case I found the reason for the problems, maybe this also helps someone else:

    The type I used as template parameter for QQmlListProperty<> was in a namespace. And even though it was in the same namespace as the class containing the QQmlListProperty I still needed to specify the full namespaces in the Q_PROPERTY declaration.

    There is actually a wiki page about this including the "Birthday example":http://qt-project.org/wiki/How_to_use_a_C_class_declared_in_a_namespace_with_Q_PROPERTY_and_QML.



  • Ok, I think at least in my case I found the reason for the problems, maybe this also helps someone else:

    The type I used as template parameter for QQmlListProperty<> was in a namespace. And even though it was in the same namespace as the class containing the QQmlListProperty I still needed to specify the full namespaces in the Q_PROPERTY declaration.

    There is actually a wiki page about this including the "Birthday example":http://qt-project.org/wiki/How_to_use_a_C_class_declared_in_a_namespace_with_Q_PROPERTY_and_QML.



  • @swegmann I ran into the same problem, and fully qualifying my namespaced payload type in the QQmlListProperty<> template inside the Q_PROPERTY() declaration indeed solved it for me. Thanks!



  • I ran into exactly the same problem and this comment saved me, @swegmann. Thank you. I reported it as a bug on the bugtracker: https://bugreports.qt.io/browse/QTBUG-84263


Log in to reply