QML 类型注册

QML 类型注册: QML 类型注册用于在QML 中申明一个在C++ 中定义的类型。让该类型或者数据可以在QML 中进行访问。

  • 匿名类型 : qmlRegisterAnonymousType
    作为一个 属性值 被QML 绑定使用,
  • 扩展类型 : qmlRegisterExtendedType
    不修改现有类型,新增一个类来拓展原类型的属性
  • 不可实例化的扩展类型 : qmlRegisterExtendedUncreatableType
    当拓展类型只计划增加附加属性、枚举值、或者是一个拓展类型的虚基类时使用。
  • 接口类型: qmlRegisterInterface
    申明一个接口类给元对象系统
  • 注册模块: qmlRegisterModule
    手动注册一个模块,这对模块保持版本同步很有用, 例如在新版本的模块中,对原来版本的模块同步到本版本模块中
  • 注册修订:qmlRegisterRevision
    注册基类的修订,以用于类型的指定版本
  • 单例类型: qmlRegisterSingletonType
    提供任意功能(方法和属性),而不需要客户端实例化该类型的单个实例 时,可以注册一个单例对象
  • qmlRegisterType 注册QObject 类型
    注册一个类型,让该类型在QML 中可以创建新的实例或者调用该类型的方法与数据
  • qmlRegisterUncreatableType 注册一个不可实例化的对象
    当一个对象仅仅用来包含一些枚举或者属性时有用
  • qmlRegisterTypeNotAvailable 注册一个不可用类型
    禁用一个QML 不可用的类型,在创建时,将给出指定错误消息
  • qRegisterMetaType 元类型
    注册一个元对象类型,让该类型可以在属性系统中可用
  • qmlRegisterUncreatableMetaObject 注册枚举
    注册一个不是实例化的元对象
qmlRegisterAnonymousType

syntax:

template <typename T> int qmlRegisterAnonymousType(const char *uri, int versionMajor)

该模板函数将一个c++ 类型作为匿名类型注册到QML中,注册的类型将没有名字,因此也无法在QML中实例化这个类型。但是当该类型的实例作为其他类型的属性时,QML 可以访问它。

在这个类型不需要名称来引用,特别是 它作为一个左值属性时 可以使用该函数。

示例:

 class Bar : public QObject
 {    
    Q_OBJECT    
    Q_PROPERTY(QString baz READ baz WRITE setBaz NOTIFY bazChanged) 
 public:     
    Bar() {}     
    QString baz() const { return mBaz; }     
    void setBaz(const QString &baz)    
    {        
        if (baz == mBaz)            
            return;         
        mBaz = baz;         
        emit bazChanged();     
    } 
 signals:     
    void bazChanged();
 private:     
    QString mBaz;  
 }; 
 
 class Foo : public QObject
 {     
    Q_OBJECT     
    Q_PROPERTY(Bar *bar READ bar CONSTANT FINAL)
 public:     
    Foo() {}     
    Bar *bar()
    { 
        return &mBar;
    } 
private:     
    Bar mBar;
 };

使用 qmlRegisterType() 注册 Foo 后,在 QML 中 定义如下

 Foo {    
    bar.baz: "abc"    
    Component.onCompleted: print(bar.baz) 
}
为了让 QML 引擎 知道 Bar 类型, 需要 使用 `qmlRegisterAnonymousType` 注册 Bar
    qmlRegisterType<Foo>("App", 1, 0, "Foo");
    qmlRegisterAnonymousType<Bar>("App", 1);

在示例中,Bar 类型 时作为 Foo 的一个属性,在 Foo 中使用 作为一个左值属性(变量)被赋值

qmlRegisterExtendedType
template <typename T, typename E>
int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
  • 扩展属性
    当将现有的类和技术集成到QML中时,API通常需要调整以更好地适应声明性环境。虽然通过直接修改原始类通常可以获得最佳结果,但如果这是不可能的,或者由于某些其他原因而变得复杂,则扩展对象允许有限的扩展可能性,而无需直接修改

扩展对象向现有类型添加其他属性。扩展对象只能添加属性,不能添加信号或方法。扩展类型定义允许程序员在注册类时提供另一种类型,称为扩展类型。当从QML中使用时,这些属性将透明地与原始目标类合并。例如:

QLineEdit{
leftMargin:20
}

在没有修改源代码的情况下,leftMargin属性成为了QLineEdit类中的新属性。

  • 示例
    我们扩展QLineEdit 然后添加一些额外的属性。

-- LineEditExtension 
class LineEditExtension : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int leftMargin READ leftMargin WRITE setLeftMargin NOTIFY marginsChanged)
    Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin NOTIFY marginsChanged)
    Q_PROPERTY(int topMargin READ topMargin WRITE setTopMargin NOTIFY marginsChanged)
    Q_PROPERTY(int bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY marginsChanged)
 public:
    LineEditExtension(QObject *);

    int leftMargin() const;
    void setLeftMargin(int);

    int rightMargin() const;
    void setRightMargin(int);

    int topMargin() const;
    void setTopMargin(int);

    int bottomMargin() const;
    void setBottomMargin(int);
signals:
    void marginsChanged();

private:
    QLineEdit *m_lineedit;
};
--main
    qmlRegisterExtendedType<LineEdit, LineEditExtension>("extended",1,0,"LineEditExtension")

一个扩展类是常规的QObject,带有包含QObject指针的构造函数。但是,扩展类的创建会被推迟到第一个扩展属性被访问的时候。扩展类创建的时候目标对象会被当做父类传入。当访问原始类的属性的时候,实际访问的是扩展类中对应的属性。

此模板函数在QML系统中注册C++类型及其扩展对象,名称为qmlName,该库从uri导入,版本号由versionMajor和versionMinor组成。将在扩展对象中搜索主类型中不可用的属性。

qmlRegisterExtendedUncreatableType
template <typename T, typename E> \
int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString &reason)

当拓展类型不可创建,意图创建时,将输出 resaon 。
当拓展类型只计划增加附加属性、枚举值、或者是一个拓展类型的虚基类时使用。其他参照 qmlRegisterExtendedType

qmlRegisterInterface
template <typename T>
int qmlRegisterInterface(const char *typeName)

注册一个接口类到QML , 如果其他继承于该接口的子类,将在QML 中自动转化成 接口类

 struct FooInterface 
 { 
    public:    
    virtual ~FooInterface();     
    virtual void doSomething() = 0;
 }; 
 Q_DECLARE_INTERFACE(FooInterface, "org.foo.FooInterface")

以这种方式注册,它可以被 用作属性类型

 Q_PROPERTY(FooInterface *foo READ foo WRITE setFoo)
qmlRegisterModule
void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)

此函数使用versionMajor和versionMinor中指定的版本在特定uri中注册模块。
这可以用于使某个模块版本可用,即使没有为该版本注册类型。这对于保持相关模块的版本同步特别有用。
Qt 5.9中介绍了该功能。

qmlRegisterRevision
template <typename T, int metaObjectRevision>
int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor)

此函数通常用于注册基类的修订,以用于类型的指定版本(请参见类型修订和版本)。

qmlRegisterSingletonType 单例类型
int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, QJSValue (*)(QQmlEngine *, QJSEngine *) callback)

允许开发人员向客户端提供任意功能(方法和属性),而不需要客户端实例化该类型的单个实例 时,可以注册一个单例对象
单个类型可以是QObject或QJSValue。此函数应用于注册一个单例类型提供程序函数,该函数将QJSValue作为单例类型返回。
示例:

 //首相定义一个提供单例对象的 静态初始化函数
 static QJSValue example_qjsvalue_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine) { 
        Q_UNUSED(engine)     
        static int seedValue = 5;     
        QJSValue example = scriptEngine->newObject();     
        example.setProperty("someProperty", seedValue++);     
        return example;
 }
 // 2. 通过调用该初始化函数 注册单例类型到 QML 
 qmlRegisterSingletonType("Qt.example.qjsvalueApi", 1, 0, "MyApi", example_qjsvalue_singletontype_provider);
 
//当然也可以使用 lamda 表达式来替代静态初始化函数
 qmlRegisterSingletonType("Qt.example.qjsvalueApi", 1, 0, "MyApi", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QJSValue {            Q_UNUSED(engine)   
    static int seedValue = 5;    
    QJSValue example = scriptEngine->newObject();     
    example.setProperty("someProperty", seedValue++);     
    return example;
    });
    In order to use the registered singleton type in QML, you must import the singleton type.
    //使用使用该对象,需要import 单例类型
    import QtQuick 2.0
    import Qt.example.qjsvalueApi 1.0 as ExampleApi 
    Item {    
        id: root     
        property int someValue: ExampleApi.MyApi.someProperty
     }
qmlRegisterSingletonType 单例对象
template <typename T> 
int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject *(*)(QQmlEngine *, QJSEngine *) callback)
//重载
template <typename T> 
int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, std::function<QObject *(QQmlEngine *, QJSEngine *)> callback)

与 下面的不同的是, 多了一个模板,且返回对象是 QObject* 对象指针

int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, QJSValue (*)(QQmlEngine *, QJSEngine *) callback)

示例:

// 首先定义一个继承与QObject 或者  QJSValue 的类
class SingletonTypeExample : public QObject
{     
    Q_OBJECT     
    Q_PROPERTY(int someProperty READ someProperty WRITE setSomeProperty NOTIFY somePropertyChanged) 
public:     
    explicit SingletonTypeExample(QObject* parent = nullptr)
        : QObject(parent) {}     
        
    Q_INVOKABLE int doSomething()     
    {        
            setSomeProperty(5);        
            return m_someProperty;     
     }     
     
     int someProperty() const { return m_someProperty; }     
     void setSomeProperty(int val)
     { 
            if (m_someProperty != val) {
            m_someProperty = val;             
            emit somePropertyChanged(val);        
            }  
     }
signals:     
        void somePropertyChanged(int newValue);
 private:     
        int m_someProperty = 0;
  };
  
 // 2.定义一个产生单例回调函数
 static QObject *example_qobject_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine) {     Q_UNUSED(engine)     Q_UNUSED(scriptEngine)     SingletonTypeExample *example = new SingletonTypeExample();     return example; }
 
  
  // 3. 注册该单例对象
  qmlRegisterSingletonInstance("Qt.example.qobjectSingleton", 1, 0, "MyApi", example.get());

使用单例对象如下

 import QtQuick 2.0 
 import Qt.example.qobjectSingleton 1.0 
 
 Item {     
    id: root     
    property int someValue: MyApi.someProperty     
    Component.onCompleted: {  
        console.log(MyApi.doSomething())    
    } 
}
qmlRegisterSingletonType 单例QML
int qmlRegisterSingletonType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)
 // 首先提供一个单例的QML 对象
 
 pragma Singleton 
 import QtQuick 2.0 
    Item {     
        property int testProp1: 125 
 } 
 //2. 使用该函数注册QML 单例类型 
 qmlRegisterSingletonType(QUrl("file:///absolute/path/SingletonType.qml"), "Qt.example.qobjectSingleton", 1, 0, "RegisteredSingleton");
 
 //为了使用该单例QML 对象,你必须 import 该类型
 import QtQuick 2.0
 import Qt.example.qobjectSingleton 1.0
 
 Item {    
    id: root     
     property int someValue: RegisteredSingleton.testProp1
 }
qmlRegisterType 注册QObject 类型
 template<typename T>
    int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
    
 template<typename T, int metaObjectRevision> 
    int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName);

将一个 C++ QObject 对象 注册到 QML 中,让QML 可以创建其实例

qmlRegisterType 注册QML 类型

此函数在QML系统中注册一个名为qmlName的类型,该类型从uri导入,版本号由versionMajor和versionMinor组成。类型由位于url的QML文件定义。url必须是绝对url,即url。isRelative()==假。

通常,可以直接从其他QML文件或使用qmldir文件将QML作为类型加载。此函数允许从C++代码向类型注册文件,例如在启动时需要以过程方式确定类型映射时。

qmlRegisterUncreatableType
template <typename T> int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString &message)

当一个类型值提供 属性 或者 枚举值时,可以使用

qmlRegisterTypeNotAvailable

如果一个C++ 类型不可以用(例如该类型是一个插件,但是未找到),我们使用该类型,给出一个 保留的类型名称,并且在的不可用的时候获得一个消息
示例

#ifdef NO_GAMES_ALLOWED 
    qmlRegisterTypeNotAvailable("MinehuntCore", 0, 1, "Game", "Get back to work, slacker!"); 
#else 
    qmlRegisterType<MinehuntGame>("MinehuntCore", 0, 1, "Game");
#endif

//在QML 意图创建该对象时,该对象返回了一个消息:Get back to work, slacker!

Game {    ^
qRegisterMetaType 注册元对象类型
template <typename T>
int qRegisterMetaType(const char *typeName)

注册一个类型,让该类型可以在属性系统和信号消息中使用

qmlRegisterUncreatableMetaObject 注册枚举
int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString &reason)

该函数注册一个 staticMetaObject 和其扩展 到 QML 系统中,
该元对象不可创建,在试图创建时会返回 reason 消息

示例:

 namespace MyNamespace {   
    Q_NAMESPACE   
    enum MyEnum {  
        Key1,      
        Key2,  
    };   
    Q_ENUMS(MyEnum)
 } //... 
 qmlRegisterUncreatableMetaObject(MyNamespace::staticMetaObject, "io.qt", 1, 0, "MyNamespace", "Access to enums & flags only");
//在 QML 中,你可以使用注册的枚举
    Component.onCompleted: console.log(MyNamespace.Key2)
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值