Dcow
Dcow

Reputation: 1463

Attached properties in QML

Can I create my own attached for everything property like a Component?

Item{
    Component.onCompleted : {} // Component is attached to everyone Items
}

Upvotes: 5

Views: 4476

Answers (2)

magrif
magrif

Reputation: 480

Yes, for example:

#include <QQmlEngine>
#include <QTimer>

class TestAttached : public QObject
{
    Q_OBJECT
    // Declare property with setter and getter
    Q_PROPERTY(int val READ getVal WRITE setVal)
public:
    TestAttached() Q_DECL_EQ_DEFAULT;
    explicit TestAttached(QObject *parent):
        QObject{parent},
        m_val{100500}
    {
        Q_ASSERT(parent);
        qDebug() << "* We just have created the object of attached properties for" << parent->metaObject()->className();
    }
    ~TestAttached() Q_DECL_EQ_DEFAULT;
    
    // define static function qmlAttachedProperties(QObject *object)
    // which returns pointer to instance of TestAttached class
    static TestAttached *qmlAttachedProperties(QObject *object)
    {
        TestAttached* testAttached { new TestAttached{object} };
        QTimer* timer { new QTimer{testAttached} };
        connect(timer, &QTimer::timeout,
        [testAttached] {
            testAttached->setVal(testAttached->getVal()+1);
            emit testAttached->testDone(testAttached->getVal());
        });
        timer->start(3000);
        return testAttached;
    }

    inline int getVal() const
    {
        return m_val;
    }
    inline void setVal(int val)
    {
        m_val = val;
    }

signals:
    void testDone(int val);

private:
    int m_val;
};
// Makes the type TestAttached known to QMetaType (for using with QVariant)
QML_DECLARE_TYPE(TestAttached)
// declares that the TestAttached supports attached properties.
QML_DECLARE_TYPEINFO(TestAttached, QML_HAS_ATTACHED_PROPERTIES)

Register attached type in QML system (e.g. at main.cpp):

qmlRegisterUncreatableType<TestAttached>("my.test", 1, 0, "Test", QObject::tr("Test is an abstract type that is only available as an attached property."));

And try it in main.qml:

import QtQuick 2.15
import QtQuick.Window 2.15
//import our module
import my.test 1.0

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World of Attached properties")

    Rectangle {
        color: focus ? Qt.lighter("red") : "red"
        width: parent.width/2; height: parent.height
        anchors.left: parent.left
        Component.onCompleted: {
            console.log("Rectangle is completed", Test.val)
        }
        Keys.onReturnPressed: {
            console.log("Rect 1: Attachet value is", Test.val)
        }

        Test.val: 20000

        Test.onTestDone: function(num) {
            console.log("We received", num, "from attached object")
        }

        MouseArea {
            anchors.fill: parent
            onClicked: parent.focus = true
        }
    }

    Rectangle {
        color: focus ? Qt.lighter("blue") : "blue"
        width: parent.width/2; height: parent.height
        anchors.right: parent.right
        focus: true

        Keys.onReturnPressed: {
            // The attached object will created after return pressed
            console.log("Rect 2: Attachet value is", Test.val)
        }

        MouseArea {
            anchors.fill: parent
            onClicked: parent.focus = true
        }
    }
}

Upvotes: 2

Ajith
Ajith

Reputation: 633

You may not be able to attach properties to Items or Components you did not create. But why would you want to do that anyway?

Instead you could consider using signals and global properties.

For global properties that you can access from anywhere you can set the context property of the root context of the declarative view.

i.e,

QmlApplicationViewer viewer;
MyPropertyClass myProp;
viewer->rootContext()->setContextProperty("MyPropClass", &myProp);

Now, in your QML file you can access the properties of this class as

Rectangle {
    Text {
        text: MyPropClass.getMyPropText()
    }
    MouseArea {
        onClicked: { MyPropClass.text = "Clicked" }
    }
}

This will invoke the Q_INVOKABLE method getMyPropText() from the MyPropertyClass. and Q_PROPERTY 'text' can be set when some signal is emitted.

Would this suit you needs?

Upvotes: 2

Related Questions