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)