简体   繁体   中英

Changing members of Q_GADGET from QML

I am trying to propagate Q_GADGET as a Q_PROPERTY into QML, change it there and pass it back into C++ . I have class that derives from Q_OBJECT , which has the Q_GADGET class as a member.

class Foo : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QGadgetClass bar READ bar WRITE setBar NOTIFY barChanged)
public:
 
    ...

    QGadgetClass bar() const { return bar_; }
    void setBar(const QGadgetClass &bar) { bar_ = bar; emit barChanged(); }

    ...

signals:
    void barChanged();

private:
    QGadgetClass bar_;
}

The Q_GADGET class looks like this:

class QGadgetClass
{
    Q_GADGET
    Q_PROPERTY(AnotherQGadgetClass test READ test WRITE setTest)
    ... // there are also properties ID & name
public:
    ...
    // QGadgetClass getMyself() const { return *this; } // function explained later

    AnotherQGadgetClass test() const { return test; }
    void setTest(const AnotherQGadgetClass &test) { test_ = test; }
    ...

private:
    AnotherQGadgetClass test_;
}
Q_DECLARE_METATYPE(QGadgetClass)

I am trying to access Q_GADGET from QML classic way like accessing a Q_OBJECT , but the setters are not called. If I get AnotherQGadgetClass via getter and change it's properties, the setters are called and everything works, but for some reason I cannot manipulate the QGadgetClass . My code in QML looks like this:

Item {
    property var bar: foo.bar
    function changeBar()
    {
        console.log(bar.name) // works
        console.log(bar.id) // works
        bar.name = "New name" // the WRITE function of Q_PROPERTY(name ...) is not called
        console.log(bar.name) // shows old name

        console.log(bar.test) // prints out AnotherQGadgetClass correctly
        var temp = bar.test // copies AnotherQGadgetClass correctly
        console.log(temp.name) // prints AnotherQGadgetClass's name
        temp.name = "New temp name" // setter is called
        console.log(temp.name) // prints new name
        bar.test = temp // constructor is NOT called
        console.log(bar.test) // prints out old AnotherQGadgetClass 

        // following code works and will be explained bellow this code
        var aa = bar.getMyself() // calls the "hackish" method
        console.log(aa.name) // prints out name of QGadgetClass
        aa.name = "New name" // calls the setter
        console.log(aa.name) // prints out new name
    }
}

I have done some research already, but found nothing but this page . I have also found some very unpretty solution here and it worked, but I find it very hacky.

Note that every Q_GADGET is declared as metatype via Q_DECLARE_METATYPE(...) & is registered before usage via qRegisterMetaType<...>("...") .

Is there any prettier solution to access QGadgetClass directly from QML, without need to call getMyself() method? Why are the Q_GADGET class setters not called?

A Q_GADGET is always treated as a value type in QML: it must be passed by copying. So the object that you manipulate in QML is not the same instance that you created in C++, and property changes aren't visible in the original. Many related issues are linked from https://bugreports.qt.io/browse/QTBUG-82443

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM