在上一篇关于QML的博客《QML与指针》中讲到了在QML中如果要使用C++的类或者其他类型都必须要注册。其中注册方式之一就是使用qmlRegisterType<T>()。只要不是内建类型比如:int, QString, bool, QPoint等等,其他的类型如果要在QML中使用,都必须向QML注册,但是注册类型必须有个要求:被注册的类型都必须间接或者直接以QObject为父类。这一点就要求了枚举类型必须声明在Qt类的内部。懂C++的人都知道,将枚举声明在类的内部,在其他类中使用该枚举类型的时候,必须使用该类来引用例如:class A内部声明了一个枚举类型DataType,那么如果要在其他类中使用改枚举类型,就必须使用A::DataType这种方式。如果把枚举类型和自己写的有特定业务的class混在一起,在其他类中使用的时候会造成很多麻烦
基于这一点考虑,我们可以模仿Qt的命名空间的思想。给自己需要在QML中使用的枚举等其他类型放到一个专门的命名空间中。这样避免了类与类之间的混淆。另外,向QML注册枚举类型注册方式跟注册类不一样,注册枚举类型需要使用Q_ENUMS()来注册。先来看看代码:
#include <QObject> class HarlenTan: public QObject { Q_OBJECT Q_ENUMS(DataType) Q_ENUMS(RequestType) public: enum DataType { Type1, Type2, Type3 }; enum RequestType { Network, Comport, Filetrans }; };
上面讲到了如何注册枚举,如何给变量赋予枚举。那么很自然,我经常会有这种需求,就是在QML中调用c++函数,函数的参数就是我们注册的枚举类型比如RequestType.
函数签名如下:
void operation(RequestType tpye);
这样,我们是不是可以在QML中通过已经注册的对象或者类直接调用该函数,并给他传入枚举类型就可以了呢?方式如下:
//qml file objId.operation(HarlenTan.Network)答案是:不可以。我们类分析这个过程。首先是定义了一个局部变量 RequestType type,然后将HarlenTan.Network这个枚举赋值给这个局部变量。但是,我们又知道,凡是在QML中直接操作的成员变量都必须是通过Q_PROPERTY()方式注册过的才能使用。例如:
Q_PROPERTY(HarlenTan::RequestType reqType READ GetType WRITE SetType) //其中,GetType和SetType需要自己实现,然后系统会自动调用
意思即是说先通过 定义一个成员变量,然后注册该成员变量,然后在QML中使用 m_reqType = HarlenTan.Network传值给成员变量。然后在operation函数内部区读取m_reqType这个成员变量就可以达到目的了。
其实,在QML内部,实质就是将枚举当做int来看待。当然,仅限于在QML当中。我们可以定 property int a: HarlenTan.Network。