在 QML 中创建自定义 C++ 对象并将其存储在 C++ 模型中
Create custom C++ Object in QML and store it in a C++ Model
我用 C++ 编写了一个客户 Class(继承自 QObject),并成功地使用 QML 注册了它的类型。目前,我正在用 C++ 静态创建此 class 的对象,并将指向它们的指针存储在实现 QAbstractListModel 的模型中。在 QML 中,我可以完美地访问对象作为模型的项目。
customObject 是一个非可视对象。
我在 GUI 应用程序 (QML) 的另一部分使用委托可视化 ListView 中的对象。
但是现在我想在 QML 中动态地从我的自定义 Class 创建对象并将它们也存储在模型中。这就是我挣扎的地方。我希望我可以像这样创建一个 customObject:
import com.myProject.myCustomStuff 1.0
...
Button{
id: createObjBtn
text: "create new CustomObj"
onClicked:{
var obj = MyCustomObj;
myObjectManager.addObj(obj); // object holding the implemented QAbstactListModel
console.log(typeof(obj)); // returns [Object object]
console.log(Qt.isQtObject(obj)) // returns false
}
}
非常感谢您的想法。也许有人知道正确执行此操作的方法?
谢谢!
更新 1
应 Simon-Warta 的要求,这里是 MyCustomObj 的构造函数实现。
MyCustomObj.cpp
MyCustomObj::MyCustomObj(QObject *parent) : QObject(parent)
{
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
}
我不知道这是否是最短路线,但这应该适合您。我从其他支持者的基础知识开始。
MyCustomObj.h
class MyCustomObj : public QObject
{
Q_OBJECT
public:
// ...
Q_INVOKABLE void funfunction();
MyCustomObj.cpp
void MyCustomObj::funfunction()
{
qDebug("Fun with QML");
}
main.cpp
qmlRegisterType<MyCustomObj>("com.myProject.myCustomStuff", 1, 0, "MyCustomObj");
app.qml
import com.myProject.myCustomStuff 1.0
ApplicationWindow {
id: mainWindow
Component {
id: myComponent
MyCustomObj {
}
}
Component.onCompleted: {
var obj = myComponent.createObject(mainWindow)
if (!obj) console.error("Error creating object")
console.log(typeof(obj))
console.log(Qt.isQtObject(obj))
obj.funfunction()
}
}
createObject 可选择将属性传递给组件。
存储
既然你现在负责删除对象,我建议使用共享指针,这样当 List 被销毁时对象也被销毁。
你的 QAbstactListModel
实现,我们称它为 MyModel
有一个这样的加法器函数:
#include <memory> // for std::shared_ptr
class MyModel : public QAbstractListModel
{
Q_OBJECT
public:
// ..
Q_INVOKABLE addObj(MyCustomObj* obj)
{
objectlist_.append(std::shared_ptr<MyCustomObj>(obj));
}
private:
QList<std::shared_ptr<MyCustomObj>> objectlist_
}
您混淆了 classes 的功能意图。 QAbstractListModel
旨在作为容器的包装器,是的,您可以将容器放在 QAbstractListModel
派生的 class 中,但您不必这样做,容器可以只是关于任何 C++ class,甚至不一定是 QObject
派生的,它可以只是一个 QVector<Something>
,您可以通过指针从模型中访问它。这对于你有很多对象的情况很有用,而且并不是所有的对象都需要一直有模型,因为这些模型非常重。
你真的不需要关心所有权,把它留在 C++ 端,实际的对象创建也是如此,有一个名为的插槽,用于将新对象添加到容器中,同时还使用模型的 beginInsertRows()
和 endInsertRows()
以便通知任何视图以有效更新,新对象也应该在该插槽中创建,您可以从 QML 传递它所需的任何数据,只需确保所有数据已在 Qt 元系统中注册,因此它可以与 QVariant
一起用于 QML-C++ 互操作。
所以它应该是这样的:
myObjectManager.create(/* any needed data goes here */)
并且 create()
将最终数据传递到 C++ 端,在 C++ 端创建对象,调用 beginInsertRows()
,将对象添加到模型的底层存储,然后调用 endInsertRows()
然后你完成了。
我更愿意将所有权保留在 C++ 端(我不是明确的意思),在那里我可以控制它。在处理 C++ 和 QML 之间共享的对象所有权时,Qt 有点糟糕。理想情况下,应该有一个共享指针 class 可以在 C++ 和 QML 中工作,因此一旦对它的所有引用都消失,该对象就会被删除。但这不是 "Qt way" - Qt 共享指针不适用于 QML,标准 C++ 共享指针也不行,实际上 QML 有一个完全不同的共享引用 class,这甚至不是public API IIRC 的一部分,非常丑陋和短视的设计,只会扩大 C++ 和 QML 之间的差距以及相关的不便因素。
我用 C++ 编写了一个客户 Class(继承自 QObject),并成功地使用 QML 注册了它的类型。目前,我正在用 C++ 静态创建此 class 的对象,并将指向它们的指针存储在实现 QAbstractListModel 的模型中。在 QML 中,我可以完美地访问对象作为模型的项目。
customObject 是一个非可视对象。
我在 GUI 应用程序 (QML) 的另一部分使用委托可视化 ListView 中的对象。
但是现在我想在 QML 中动态地从我的自定义 Class 创建对象并将它们也存储在模型中。这就是我挣扎的地方。我希望我可以像这样创建一个 customObject:
import com.myProject.myCustomStuff 1.0
...
Button{
id: createObjBtn
text: "create new CustomObj"
onClicked:{
var obj = MyCustomObj;
myObjectManager.addObj(obj); // object holding the implemented QAbstactListModel
console.log(typeof(obj)); // returns [Object object]
console.log(Qt.isQtObject(obj)) // returns false
}
}
非常感谢您的想法。也许有人知道正确执行此操作的方法?
谢谢!
更新 1
应 Simon-Warta 的要求,这里是 MyCustomObj 的构造函数实现。
MyCustomObj.cpp
MyCustomObj::MyCustomObj(QObject *parent) : QObject(parent)
{
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
}
我不知道这是否是最短路线,但这应该适合您。我从其他支持者的基础知识开始。
MyCustomObj.h
class MyCustomObj : public QObject
{
Q_OBJECT
public:
// ...
Q_INVOKABLE void funfunction();
MyCustomObj.cpp
void MyCustomObj::funfunction()
{
qDebug("Fun with QML");
}
main.cpp
qmlRegisterType<MyCustomObj>("com.myProject.myCustomStuff", 1, 0, "MyCustomObj");
app.qml
import com.myProject.myCustomStuff 1.0
ApplicationWindow {
id: mainWindow
Component {
id: myComponent
MyCustomObj {
}
}
Component.onCompleted: {
var obj = myComponent.createObject(mainWindow)
if (!obj) console.error("Error creating object")
console.log(typeof(obj))
console.log(Qt.isQtObject(obj))
obj.funfunction()
}
}
createObject 可选择将属性传递给组件。
存储
既然你现在负责删除对象,我建议使用共享指针,这样当 List 被销毁时对象也被销毁。
你的 QAbstactListModel
实现,我们称它为 MyModel
有一个这样的加法器函数:
#include <memory> // for std::shared_ptr
class MyModel : public QAbstractListModel
{
Q_OBJECT
public:
// ..
Q_INVOKABLE addObj(MyCustomObj* obj)
{
objectlist_.append(std::shared_ptr<MyCustomObj>(obj));
}
private:
QList<std::shared_ptr<MyCustomObj>> objectlist_
}
您混淆了 classes 的功能意图。 QAbstractListModel
旨在作为容器的包装器,是的,您可以将容器放在 QAbstractListModel
派生的 class 中,但您不必这样做,容器可以只是关于任何 C++ class,甚至不一定是 QObject
派生的,它可以只是一个 QVector<Something>
,您可以通过指针从模型中访问它。这对于你有很多对象的情况很有用,而且并不是所有的对象都需要一直有模型,因为这些模型非常重。
你真的不需要关心所有权,把它留在 C++ 端,实际的对象创建也是如此,有一个名为的插槽,用于将新对象添加到容器中,同时还使用模型的 beginInsertRows()
和 endInsertRows()
以便通知任何视图以有效更新,新对象也应该在该插槽中创建,您可以从 QML 传递它所需的任何数据,只需确保所有数据已在 Qt 元系统中注册,因此它可以与 QVariant
一起用于 QML-C++ 互操作。
所以它应该是这样的:
myObjectManager.create(/* any needed data goes here */)
并且 create()
将最终数据传递到 C++ 端,在 C++ 端创建对象,调用 beginInsertRows()
,将对象添加到模型的底层存储,然后调用 endInsertRows()
然后你完成了。
我更愿意将所有权保留在 C++ 端(我不是明确的意思),在那里我可以控制它。在处理 C++ 和 QML 之间共享的对象所有权时,Qt 有点糟糕。理想情况下,应该有一个共享指针 class 可以在 C++ 和 QML 中工作,因此一旦对它的所有引用都消失,该对象就会被删除。但这不是 "Qt way" - Qt 共享指针不适用于 QML,标准 C++ 共享指针也不行,实际上 QML 有一个完全不同的共享引用 class,这甚至不是public API IIRC 的一部分,非常丑陋和短视的设计,只会扩大 C++ 和 QML 之间的差距以及相关的不便因素。