如何将带有指针成员的非QObject类公开给QML?

时间:2014-02-07 10:10:20

标签: c++ qt qml wrapper qobject

我了解如何通过创建一个将我的类作为成员的新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)一起使用是否常见?或者是否有另一种解决这个问题的方法?

2 个答案:

答案 0 :(得分: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());
}

答案 1 :(得分:1)

我刚刚问过类似的问题:How to expose C++ structs for computations to Qml

事实证明,没有直接的方法。但如果你看看这个问题的答案,你会看到我们如何解决它。 我们只是构建了一个包装器,并使所有相关对象成为它的成员。这些成员有自己的属性,它们只是通过包装器转发。然后你只需管理getter和setter就可以将值传递给包装器的成员。要从成员中发出对象,可以引入EmitterHelperObjects(只是小对象,它继承QObject,其唯一任务是抛出信号)。 在某些情况下,您可能需要将包装器的指针注册为MetaType。我没想出来,因为我什么时候需要这样做,什么时候不这样做。

总结一下这个方法: 您不直接使用指针,而是通过将Wrapper用作“Property forwarder”来仅访问其成员的属性。它有点打字,但效果很好。 就个人而言,我不喜欢Qt / Qml的这一面,这个对象一个身份的东西在某些情况下变得难看。

我知道你很久以前就曾问过,但也许这对别人有帮助。