从 QML 动态创建 C++ 对象
Dynamically create C++ object from QML
我想从 QML
动态创建一个 C++
对象。我创建了一个名为 Car
的 QObject
派生 class,并使用 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
因为没有 *.qml
文件其中定义了 Car
,因为 Car
是在 C++
.[=33= 中定义的]
您可以使用 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
}
正如我在评论中所说,问题是变量component
,当时不存在。
因此,要解决此问题,只需替换以下代码:
onClicked: {
component = Qt.createQmlObject(...);
作者:
onClicked: {
var component = Qt.createQmlObject(...);
其实所有的qml对象都是动态分配的。在你的情况下 Car
也有。 Loader
和其他替代方案只是为了通过 qml 引导它。所以如果你想在 C++ 端传递一个 qml 对象,你唯一需要的是一个带有 Car * 参数的 slot/invokable 函数。在您的 slot/invokable 函数中,您必须指定您正在将对象所有权交给 qml 引擎。
假设你有一辆汽车 class 类似这样的东西,
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;
};
还有一家商店class与此类似,
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
}
我想从 QML
动态创建一个 C++
对象。我创建了一个名为 Car
的 QObject
派生 class,并使用 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
因为没有 *.qml
文件其中定义了 Car
,因为 Car
是在 C++
.[=33= 中定义的]
您可以使用 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
}
正如我在评论中所说,问题是变量component
,当时不存在。
因此,要解决此问题,只需替换以下代码:
onClicked: {
component = Qt.createQmlObject(...);
作者:
onClicked: {
var component = Qt.createQmlObject(...);
其实所有的qml对象都是动态分配的。在你的情况下 Car
也有。 Loader
和其他替代方案只是为了通过 qml 引导它。所以如果你想在 C++ 端传递一个 qml 对象,你唯一需要的是一个带有 Car * 参数的 slot/invokable 函数。在您的 slot/invokable 函数中,您必须指定您正在将对象所有权交给 qml 引擎。
假设你有一辆汽车 class 类似这样的东西,
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;
};
还有一家商店class与此类似,
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
}