从QML动态创建C++对象

7

我想要从QML动态创建一个C++对象。我创建了一个继承自QObject的类,名为Car,并使用 qmlRegisterType<Car>("org.qtproject.models", 1, 0, "Car"); 将其导入到QML中。在QML中,我可以这样实例化一个Car对象:

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

如果需要,我可以轻松地使用car_1对象并将其传回到C ++。但是我希望能够在QML中动态创建一个Car对象,以便可以将其传回到C ++

我尝试过:

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

        myCarModel.appendRowFromQml(component);
    }
}

但是没有运气。使用静态方法,工作得很好:
MouseArea
{
    anchors.fill: parent
    onClicked: {
        myCarModel.appendRowFromQml(car_1);
    }
}

有没有一种方法可以在QML端动态创建C++对象?我也无法使用Qt.createComponent,因为没有定义Car的*.qml文件,因为Car是在C++中定义的。

我不确定,但也许问题在于你需要在传递给Qt.createQmlObject的字符串中包含import QtQuick 2.0; - Tarod
@Tarod 感谢您的回答。我也尝试了 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");,但是当代码执行时,我得到了 qrc:/main.qml:58: Error: Invalid write to global property "component" 的错误提示... - Jacob Krieg
3
如果你写var component = Qt.createQmlObject而不是component = Qt.createQmlObject,你会遇到相同的问题吗? - Tarod
@Tarod 那就是问题所在。糟糕...请写一个答案,这样我就可以接受它了 :) 非常感谢!!! - Jacob Krieg
1
好的,谢谢你!愉快编程 :) - Tarod
3个回答

3
您可以使用Loader来实现。例如:
Loader {
   id: carLoader
   active: false
   sourceComponent:
   Car {
       id : car_1
       carName : "H1"
       carBrand : "Hummer"
       carPrice : 125000
   } 

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

2

如我在评论中所说,问题出在变量component在那个时候并不存在。

因此,为了解决这个问题,只需要替换以下代码:

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

by:

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

1

实际上,所有的QML对象都是动态分配的。在您的情况下,Car 也是如此。 Loader 和其他替代方案只是为了在QML中指向它。因此,如果您想在C++端传递一个QML对象,则需要拥有一个带有Car *参数的槽/可调用函数。在您的槽/可调用函数中,您必须指定将对象所有权转移给QML引擎。

假设您有一个类似于这样的汽车类,

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;
};

还有一个类似于这样的 Store 类:

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

    Q_INVOKABLE void sell(Car *car);
};

如果你将你的Car对象传递给qml上的Store对象,

Car {
    id: car1
    name: "H1"
}

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

那么在您的销售函数中,您必须指定对象所有权。
void Store::sell(Car *car)
{
    qDebug() << car->name() << "just sold!!";
    QQmlEngine::setObjectOwnership(car, QQmlEngine::CppOwnership);
    delete car; // proof of the car is dynamically allocated
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接