如何将具有指向 QML 的指针成员的非 QObject 类公开?
Posted
技术标签:
【中文标题】如何将具有指向 QML 的指针成员的非 QObject 类公开?【英文标题】:How do I expose a non-QObject class with pointer members to QML? 【发布时间】:2014-02-07 10:10:20 【问题描述】:我了解如何通过创建一个以我的类为成员的新 QObject
类来公开简单的数据成员。例如:
class MyClass
public:
int anInt;
;
还有包装器
class MyClassQWrapped : public QObject
Q_OBJECT
Q_PROPERTY(int anInt READ anInt write setAnInt NOTIFY anIntChanged)
public:
int anInt()return myClass.anInt;
void setAnInt(int value)
if(myClass.anInt==value)return;
myClass.anInt = value;
emit anIntChanged;
signals:
anIntChanged();
private:
MyClass myClass;
;
但是如何用指针数据成员包装对象呢?比如说我有一个链表类,想把它暴露给 qml:
Class LinkedList
public:
int anInt;
LinkedList *next;
;
我不能使用与上面相同的方法,因为这样包装器的属性将是指向LinkedList
,而不是LinkedListQWrapped
的指针。如果列表由非 Qt 代码更改,我无法知道哪个(如果有)LinkedListQWrapped
对象对应于给定的LinkedList*
。
现在,我可以更改 c++ 模型,但我不能让它依赖于 Qt。
我可以想到一种解决方案,将void*
用户数据成员添加到 c++ 类,然后在创建包装器后将其设置为指向相应的包装对象。
我在box2d看到过这种事情。
这是解决问题的推荐方法吗?在库代码中提供void*
用户数据成员以使它们与各种框架(如Qt)配合使用是否很常见?或者这个问题有其他解决方案吗?
【问题讨论】:
【参考方案1】:我不相信您可以将非QObject
派生类公开给 QML,因为我知道的唯一方法是通过 QQmlContext
。
查看 QML box2d 扩展,似乎所有面向 QML 的类都以某种方式派生自 QObject
,请看这里 box2d repo。
也就是说他们确实使用包装函数在 QML box2d 类型和常规非QObject
类型之间进行转换。即
/**
* Convenience function to get the Box2DJoint wrapping a b2Joint.
*/
inline Box2DJoint *toBox2DJoint(b2Joint *joint)
return static_cast<Box2DJoint*>(joint->GetUserData());
【讨论】:
啊,太好了!不知道 box2d 有 QML 扩展。这可能也是我将要这样做的方式。这将是很好的参考。【参考方案2】:我刚刚问了一个类似的问题:How to expose C++ structs for computations to Qml
事实证明,没有直接的方法。但是,如果您查看对该问题的回答,您会看到我们是如何解决它的。 我们简单地构建了一个包装器,并让所有相关的对象成为它的成员。这些成员有自己的属性,它们只是通过包装器转发。然后您只需管理 getter 和 setter 即可将值传递给包装器的成员。对于从成员发射对象,您可以引入 EmitterHelperObjects(只是继承 QObject 并且其唯一任务是抛出信号的小对象)。 在某些情况下,您可能需要将包装器的指针注册为 MetaType。我还没弄清楚,什么时候需要,什么时候不需要。
所以总结一下方法: 您不直接使用指针,而是通过将 Wrapper 用作“属性转发器”来仅访问其成员的属性。它有点打字,但效果很好。 就个人而言,我不喜欢 Qt / Qml 的这一面,这个 Object one Identity 的东西在某些情况下变得很丑陋。
我知道你很久以前就问过了,但也许它对其他人有帮助。
【讨论】:
已经有一段时间了,但我很确定这也是我解决它的方法。正如你所说,这是很多乏味的写作,但效果很好。以上是关于如何将具有指向 QML 的指针成员的非 QObject 类公开?的主要内容,如果未能解决你的问题,请参考以下文章