7

I want to dynamically create a C++ object from QML. I created a QObject derived class named Car and exposed it to QML using qmlRegisterType<Car>("org.qtproject.models", 1, 0, "Car");. Inside QML I am able to instantiate a Car object like this:

Car {
    id : car_1
    carName : "H1"
    carBrand : "Hummer"
    carPrice : 125000
} 

and then use the car_1 object and pass it back to C++ with ease if I need to. But what I would like is to create a Car object dynamically in QML, so I can pass it back to C++.

I tried:

MouseArea
{
    anchors.fill: parent
    onClicked: {
        component = Qt.createQmlObject("Car { id: car_1; carName : \"H1\"; carBrand : \"Hummer\"; carPrice : 125000; }",
                                       parent, "dynamicSnippet1");

        myCarModel.appendRowFromQml(component);
    }
}

but no luck. With the static approach, works fine:

MouseArea
{
    anchors.fill: parent
    onClicked: {
        myCarModel.appendRowFromQml(car_1);
    }
}

Is there a way to dynamically create a C++ object from the QML side? I also couldn't use Qt.createComponent because there is no *.qml file in which Car is defined, as Car was defined in C++.

5
  • I'm not sure, but maybe the problem is you need to include import QtQuick 2.0; in the string passed to Qt.createQmlObject Commented May 16, 2016 at 12:26
  • @Tarod Thanks for the answer. I also tried component = Qt.createQmlObject("import QtQuick 2.4; import org.qtproject.models 1.0; Car { id: car_1; carName : \"H1\"; carBrand : \"Hummer\"; carPrice : 125000; }", parent, "dynamicSnippet1"); and I get qrc:/main.qml:58: Error: Invalid write to global property "component" when the code gets executed... Commented May 16, 2016 at 12:31
  • 3
    Do you get the same issue if you write var component = Qt.createQmlObject instead of component = Qt.createQmlObject? Commented May 16, 2016 at 12:36
  • @Tarod That was the problem. Crap...write an answer so I can accept it :) Thanks a lot!!! Commented May 16, 2016 at 12:38
  • 1
    Well, thanks to you! Happy coding :) Commented May 16, 2016 at 13:44

3 Answers 3

2

As I said in the comments, the problem is the variable component, which doesn't exist at that time.

So to fix the problem it is enough to replace the following code:

onClicked: {
    component = Qt.createQmlObject(...);

by:

onClicked: {
    var component = Qt.createQmlObject(...);
Sign up to request clarification or add additional context in comments.

Comments

2

You can use a Loader .

Something like this:

Loader {
   id: carLoader
   active: false
   sourceComponent:
   Car {
       id : car_1
       carName : "H1"
       carBrand : "Hummer"
       carPrice : 125000
   } 

MouseArea
{
    anchors.fill: parent
    onClicked: carLoader.active:true
}

Comments

1

Actually all qml objects are dynamically allocated. In your case Car has also. Loader and other alternatives are just for directing it over qml. So if you like to pass a qml object on C++ side, the only thing you need to have a slot/invokable function with Car * parameter. In your slot/invokable function, you must specify that you are taking the objects ownership to qml engine.

Suppose you have a Car class something similar like this,

class Car : public QObject {
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)

public:
    explicit Car(QObject *parent = Q_NULLPTR);
    ~Car();

    QString name();
    void setName(const QString &name);

signals:
    void nameChanged();

private:
    QString m_name;
};

And a Store class similar to this,

class Store : public QObject {
    Q_OBJECT
public:
    explicit Store(QObject *parent = Q_NULLPTR);

    Q_INVOKABLE void sell(Car *car);
};

And if you pass your Car object to Store object on qml,

Car {
    id: car1
    name: "H1"
}

MouseArea {
    anchors.fill: parent
    onClicked: Store.sell(car1);
}

then you must to specify the object ownership in your sell function,

void Store::sell(Car *car)
{
    qDebug() << car->name() << "just sold!!";
    QQmlEngine::setObjectOwnership(car, QQmlEngine::CppOwnership);
    delete car; // proof of the car is dynamically allocated
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.