QQmlEngine类

QQmlEngine类提供了一个部署QML组件的环境。 更多...

头文件 #include <QQmlEngine>
CMakefind_package(Qt6 REQUIRED COMPONENTS Qml)
target_link_libraries(mytarget PRIVATE Qt6::Qml)
qmakeQT += qml
继承于 QJSEngine
由以下类继承

QQmlApplicationEngine

属性

公共函数

QQmlEngine(QObject *parent = nullptr)
virtual~QQmlEngine() override
voidaddImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
voidaddImportPath(const QString &path)
voidaddPluginPath(const QString &path)
voidaddUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
QUrlbaseUrl() const
void清除组件缓存()
void清除单例对象()
QQmlImageProviderBase *imageProvider(const QString &providerId) const
QStringListimportPathList() const
QQmlIncubationController *incubationController() const
QUrlinterceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const
(自6.6起) void将当前函数标记为翻译绑定()
QNetworkAccessManager *networkAccessManager() const
QQmlNetworkAccessManagerFactory *networkAccessManagerFactory() const
QStringofflineStorageDatabaseFilePath(const QString &databaseName) const
QStringofflineStoragePath() const
booloutputWarningsToStandardError() const
QStringListpluginPathList() const
voidremoveImageProvider(const QString &providerId)
voidremoveUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
QQmlContext *rootContext() const
voidsetBaseUrl(const QUrl &url)
voidsetImportPathList(const QStringList &paths)
voidsetIncubationController(QQmlIncubationController *controller)
voidsetNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
voidsetOfflineStoragePath(const QString &dir)
voidsetOutputWarningsToStandardError(bool enabled)
voidsetPluginPathList(const QStringList &paths)
TsingletonInstance(int qmlTypeId)
(since 6.5) TsingletonInstance(QAnyStringView uri, QAnyStringView typeName)
voidtrimComponentCache()
QList<QQmlAbstractUrlInterceptor *>urlInterceptors() const

公共槽

voidretranslate()

信号

voidexit(int retCode)
(since 6.5) voidofflineStoragePathChanged()
voidquit()
voidwarnings(const QList<QQmlError> &warnings)

静态公共成员

QQmlContext *contextForObject(const QObject *object)
voidsetContextForObject(QObject *object, QQmlContext *context)

重写的受保护函数

virtual boolevent(QEvent *e) override
enumQQmlModuleImportSpecialVersions { QQmlModuleImportModuleAny, QQmlModuleImportLatest, QQmlModuleImportAuto }
QObject *qmlAttachedPropertiesObject(const QObject *attachee, bool create = true)
voidqmlClearType Registrations()
QQmlContext *qmlContext(const QObject *object)
QQmlEngine *qmlEngine(const QObject *object)
boolqmlProtectModule(const char *uri, int majVersion)
intqmlRegisterAnonymousType(const char *uri, int versionMajor)
intqmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
intqmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString &reason)
voidqmlRegisterModule(const char *uri, int versionMajor, int versionMinor)
voidqmlRegisterModuleImport(const char *uri, int moduleMajor, const char *import, int importMajor = QQmlModuleImportLatest, int importMinor = QQmlModuleImportLatest)
intqmlRegisterRevision(const char *uri, int versionMajor, int versionMinor)
intqmlRegisterSingletonInstance(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject *cppObject)
intqmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, std::function<QJSValue (QQmlEngine *, QJSEngine *)> callback)
intqmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, std::function<QObject *(QQmlEngine *, QJSEngine *)> callback)
intqmlRegisterSingletonType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)
intqmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
intqmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)
intqmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString &message)
intqmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject, const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString &reason)
intqmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString &message)
intqmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
voidqmlUnregisterModuleImport(const char *uri, int moduleMajor, const char *import, int importMajor = QQmlModuleImportLatest, int importMinor = QQmlModuleImportLatest)

宏定义

详细描述

QQmlEngine用于管理由它们创建的组件和对象,并执行它们的绑定和函数。QQmlEngine还继承自QJSEngine,允许您的QML组件和JavaScript代码实现无缝集成。

每个QML组件都在一个QQmlContext中实例化。在QML中,上下文按层次结构排列,这个层次结构由QQmlEngine管理。默认情况下,组件在根上下文中实例化。

另请参阅QQmlComponentQQmlContextQML全局对象QQmlApplicationEngine

属性文档

offlineStoragePath : QString

此属性持有存储离线用户数据的目录

返回SQL和其他离线存储放置的目录。

使用openDatabaseSync()创建的SQL数据库存储在这里。

默认值是平台标准用户应用程序数据目录中的QML/OfflineStorage。

请注意,该路径可能当前不在文件系统中存在,因此希望在此位置创建新文件的调用者应首先创建该路径 - 请参阅QDir::mkpath

访问函数

QStringofflineStoragePath() const
voidsetOfflineStoragePath(const QString &dir)

通知器信号

参见Qt Quick Local Storage QML 类型.

成员函数文档

[显式] QQmlEngine::QQmlEngine(QObject *parent = nullptr)

创建一个新的 QQmlEngine,其父对象为 parent

[重写虚函数 noexcept] QQmlEngine::~QQmlEngine()

销毁 QQmlEngine。

在此引擎上创建的任何 QQmlContext 都会被废止,但不会被销毁(除非它们是 QQmlEngine 对象的父对象)。

有关清理 JS 引擎的详细信息,请参见 ~QJSEngine

void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)

设置用于通过 image: url 方案请求图片的 provider。QQmlEngine 将获取 provider 的所有权。

图片提供者支持 pixmap 和线程化图像请求。有关实现和使用图像提供者的详细信息,请参阅 QQuickImageProvider 文档。

应在加载任何 QML 源文件之前将所有必需的图像提供者添加到引擎中。

参见removeImageProviderQQuickImageProviderQQmlImageProviderBase

void QQmlEngine::addImportPath(const QString &path)

path 添加为一个目录,引擎将在基于 URL 的目录结构中搜索安装的模块。

path 可以是一个本地文件系统目录、一个 Qt 资源 路径(:/imports)、一个 Qt 资源 URL(qrc:/imports)或一个 URL。

在将 path 添加到导入路径列表之前,它将转换为规范形式。

新添加的 path 将首先出现在 importPathList 中。

参见setImportPathListQML 模块QML 导入路径

void QQmlEngine::addPluginPath(const QString &path)

path 添加为一个目录,引擎将在其中搜索导入模块的本地插件(在 qmldir 文件中引用)。

默认情况下,列表中只包含 .,即引擎在 qmldir 文件所在的目录中进行搜索。

新添加的 path 将首先出现在 pluginPathList 中。

参见setPluginPathList

void QQmlEngine::addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)

在QML中解析URL时添加用于的urlInterceptor。这也适用于用于加载脚本文件和QML类型的URL。在引擎加载文件时不应修改URL拦截器,否则URL选择可能会有误。如果提供了多个URL拦截器,它们将按添加顺序针对每个URL调用。

QQmlEngine不会接管拦截器的所有权,也不会删除它。

QUrl QQmlEngine::baseUrl() const

返回此引擎的基本URL。基本URL仅用于在将相对URL传递给QQmlComponent构造函数时解析组件。

如果没有显式设置基本URL,则此方法返回应用程序的当前工作目录。

另请参阅setBaseUrl()。

void QQmlEngine::clearComponentCache()

清除引擎的内部组件缓存。

此函数会销毁引擎先前加载的所有组件的属性元数据。所有先前加载的组件以及从这些组件创建的所有现有对象的属性绑定都将停止工作。

此函数使引擎回到不包含任何加载组件数据的状态。这可以用来重新加载先前组件集的一小部分,或加载先前加载组件的新版本。

清除组件缓存后,在创建任何新对象之前必须加载组件。

注意:从QML组件创建的任何现有对象保留其类型,即使已清空组件缓存。这包括单例对象。如果在清空缓存后从中创建更多对象,新对象将与旧对象的类型不同。将此类新对象分配给在清空缓存之前创建的对象的声明类型属性时,将不起作用。

一般来说,确保在清除组件缓存时,没有任何从QML组件创建的对象是活跃的。

另请参阅trimComponentCache() 和 clearSingletons()。

void QQmlEngine::clearSingletons()

清除引擎拥有的所有单例。

此函数丢弃所有单例实例,并删除其中任何由引擎拥有的QObjects。这可以确保在调用clearComponentCache()之前,不留下任何由QML创建的对象。

如果引擎拥有单例,则持有QObject基于单例实例的QML属性变为null,如果引擎不拥有它,则保留其值。单例不会被自动重新创建,直到通过访问现有的由QML创建的对象。

另请参阅clearComponentCache()。

[静态] QQmlContext *QQmlEngine::contextForObject(const QObject *object)

返回对象QQmlContext,如果没有设置上下文,则返回nullptr。

QQmlEngine实例化QObject时,将自动为其分配一个内部上下文。此类内部上下文是只读的。您无法在它们上面设置上下文属性。

请参阅setContextForObject(),qmlContext(),qmlEngine()和QQmlContext::setContextProperty

[重写虚保护] bool QQmlEngine::event(QEvent *e)

重新实现: QObject::event(QEvent *e)

[信号] void QQmlEngine::exit(int retCode)

当由引擎加载的QML想要以指定的返回代码retCode退出事件循环时,将发出此信号。

请参阅quit

QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const

如果找到,返回为providerId设置的图像提供者;否则返回nullptr

请参阅QQuickImageProvider

QStringList QQmlEngine::importPathList() const

返回引擎在基于URL的目录结构中搜索已安装模块的目录列表。

例如,如果路径中包含/opt/MyApp/lib/imports,则导入com.mycompany.Feature的QML将导致QQmlEngine/opt/MyApp/lib/imports/com/mycompany/Feature/中查找该模块提供的组件。需要一个qmldir文件来定义类型版本映射以及可能的QML扩展插件。

默认情况下,此列表包含QML导入路径中提到的路径。

请参阅addImportPath()和setImportPathList

QQmlIncubationController *QQmlEngine::incubationController() const

返回当前设置的孵化控制器,如果没有设置控制器,则返回0。

请参阅setIncubationController

QUrl QQmlEngine::interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const

在给定type的给定url上运行当前URL拦截器,并返回结果。

[自6.6起] void QQmlEngine::markCurrentFunctionAsTranslationBinding()

如果在此方法调用的是QML中绑定的一部分函数,则该绑定将被视为翻译绑定。

class I18nAwareClass : public QObject {

  //...

   QString text() const
   {
        if (auto engine = qmlEngine(this))
            engine->markCurrentFunctionAsTranslationBinding();
        return tr("Hello, world!");
   }
};

注意:此功能主要用于您想要提供一个替代qsTr函数的功能。为了确保从C++类暴露的属性在语言更改时更新,建议响应LanguageChange事件。这是一个更通用的机制,当类在非QML环境中使用时也适用,并且开销略小。然而,当类已经与QML引擎紧密关联时,使用markCurrentFunctionAsTranslationBinding是可以接受的。有关更多详细信息,请参阅准备动态语言更改

该函数自Qt 6.6版本引入。

另请参阅:QQmlEngine::retranslate.

QNetworkAccessManager *QQmlEngine::networkAccessManager() const

返回一个公共的QNetworkAccessManager,可以被此引擎实例化的任何QML类型使用。

如果已经设置了QQmlNetworkAccessManagerFactory且尚未创建QNetworkAccessManager,则QQmlNetworkAccessManagerFactory将被用于创建QNetworkAccessManager;否则返回的QNetworkAccessManager将没有设置代理或缓存。

另请参阅:setNetworkAccessManagerFactory().

QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const

返回当前的QQmlNetworkAccessManagerFactory

另请参阅:setNetworkAccessManagerFactory().

QString QQmlEngine::offlineStorageDatabaseFilePath(const QString &databaseName) const

返回一个标识为databaseNameLocal Storage数据库的位置(或将要位于的位置)的文件路径。

另请参阅:LocalStorage.openDatabaseSync().

[信号,自6.5版本起] void QQmlEngine::offlineStoragePathChanged()

offlineStoragePath改变时,会发出此信号。

注意:这是属性offlineStoragePath的通知信号。

该函数自Qt 6.5版本引入。

bool QQmlEngine::outputWarningsToStandardError() const

如果警告消息除了通过warnings信号发出外还会输出到stderr,则返回true,否则返回false。

默认值为true。

另请参阅:setOutputWarningsToStandardError().

QStringList QQmlEngine::pluginPathList() const

返回引擎搜索原生插件导入模块(在qmldir文件中引用)的目录列表。

默认情况下,列表中只包含 .,即引擎在 qmldir 文件所在的目录中进行搜索。

另请参阅:addPluginPath() 和 setPluginPathList().

[信号] void QQmlEngine::quit()

当由引擎加载的QML希望退出时,会发出此信号。

另请参阅:exit().

void QQmlEngine::removeImageProvider(const QString &providerId)

移除图像提供程序providerId

另请参阅addImageProvider() 和 QQuickImageProvider

void QQmlEngine::removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)

移除之前使用 addUrlInterceptor 添加的 urlInterceptor。在不加载文件的过程中不应修改URL拦截器,否则URL选择可能不一致。

这不会删除拦截器,只是将其从引擎中移除。此后可以在同一或不同引擎上重新使用它。

[槽] void QQmlEngine::retranslate()

刷新所有使用标记为翻译的字符串的绑定表达式。

在您已使用 QCoreApplication::installTranslator 安装了新的翻译器之后,请调用此函数,以确保用户界面显示最新的翻译。

QQmlContext *QQmlEngine::rootContext() const

返回引擎的根上下文。

根上下文由 QQmlEngine 自动创建。应将应供所有由引擎实例化QML组件实例访问的数据放入根上下文中。

仅对组件实例的子集可用的高级数据应添加到根上下文所隶属的子上下文中。

void QQmlEngine::setBaseUrl(const QUrl &url)

将此引擎的基础URL设置为url

另请参阅baseUrl

[静态] void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)

object 设置 QQmlContextcontext。如果object 已经有上下文,则输出警告,但上下文不会更改。

QQmlEngine 实例化 QObject 时,上下文会自动设置。

另请参阅contextForObject

void QQmlEngine::setImportPathList(const QStringList &paths)

paths 设置为引擎在基于URL的目录结构中搜索已安装模块的目录列表。

默认情况下,此列表包含QML导入路径中提到的路径。

警告:调用 setImportPathList 不会保留默认导入路径。

另请参阅importPathList() 和 addImportPath

void QQmlEngine::setIncubationController(QQmlIncubationController *controller)

设置引擎的孵化控制controller。引擎只能有一个活动的控制台,并且它不会对其进行所有权。

另请参阅incubationController

void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)

设置用于创建 QNetworkAccessManager(s) 的工厂

QNetworkAccessManager 用于 QML 的所有网络访问。通过实现工厂,可以创建具有专用缓存、代理和 Cookie 支持的定制 QNetworkAccessManager

必须在执行引擎之前设置工厂。

注意: QQmlEngine 不会接管工厂的所有权。

另请参阅:networkAccessManagerFactory()。

void QQmlEngine::setOutputWarningsToStandardError(bool enabled)

将警告消息输出到 stderr 的选项设置为enabled

如果enabled为 true,则由 QML 生成的任何警告消息都将输出到 stderr 并通过 warnings() 信号发出。如果enabled为 false,则只通过 warnings() 信号发出。这允许应用程序自行处理警告输出。

默认值为true。

另请参阅:outputWarningsToStandardError()。

void QQmlEngine::setPluginPathList(const QStringList &paths)

将引擎搜索用于导入模块(在qmldir文件中引用)本机插件的目录列表设置为paths

默认情况下,列表中只包含 .,即引擎在 qmldir 文件所在的目录中进行搜索。

另请参阅:pluginPathList() 和 addPluginPath()。

template <typename T> T QQmlEngine::singletonInstance(int qmlTypeId)

返回在qmlTypeId下注册的单例类型的实例。

模板参数T可以是QJSValueQObject派生类型的指针,这取决于单例是如何注册的。如果尚未创建T的实例,则现在会创建它。如果qmlTypeId不代表一个有效的单例类型,则返回默认构造的QJSValuenullptr

QObject* 示例

class MySingleton : public QObject {
    Q_OBJECT

    // Register as default constructed singleton.
    QML_ELEMENT
    QML_SINGLETON

    static int typeId;
    // ...
};

    MySingleton::typeId = qmlTypeId(...);

    // Retrieve as QObject*
    QQmlEngine engine;
    MySingleton* instance = engine.singletonInstance<MySingleton*>(MySingleton::typeId);

QJSValue 示例

    // Register with QJSValue callback
    int typeId = qmlRegisterSingletonType(...);

    // Retrieve as QJSValue
    QQmlEngine engine;
    QJSValue instance = engine.singletonInstance<QJSValue>(typeId);

建议将 QML 类型 id 存储起来,例如作为单例类的静态成员。通过qmlTypeId()进行查找的成本很高。

另请参阅:QML_SINGLETONqmlRegisterSingletonType(),和qmlTypeId()。

[since 6.5] template <typename T> T QQmlEngine::singletonInstance(QAnyStringView uri, QAnyStringView typeName)

这是一个重载函数。

返回由uri指定的模块中命名名为typeName的单例类型的实例。

此方法可以用作在调用 qmlTypeId 后的基于id的重载的singletonInstance的替代品。当只需要对单例进行一次设置时,这非常有用;如果需要重复访问单例,缓存其typeId将允许通过 基于type-id的重载 进行更快的后续访问。

模板参数T可以是QJSValue或指向继承自QObject类型的指针,具体取决于单例的注册方式。如果尚未创建T的实例,现在将创建它。如果typeName不表示有效的单例类型,则返回一个默认构造的QJSValue或一个nullptr

    QQmlEngine engine;
    MySingleton *singleton = engine.singletonInstance<MySingleton *>("mymodule", "MySingleton");
/

该函数自Qt 6.5版本引入。

另请参阅:QML_SINGLETONqmlRegisterSingletonType(),和qmlTypeId()。

void QQmlEngine::trimComponentCache()

修剪引擎的内部组件缓存。

此函数将销毁任何当前未使用的已加载组件的属性元数据。

如果一个组件有任何实例在使用中,任何使用此组件的其他组件的实例,或者任何由这些组件之一实例化的对象,则认为该组件正在使用中。

另请参阅clearComponentCache()。

QList<QQmlAbstractUrlInterceptor *> QQmlEngine::urlInterceptors() const

返回当前活动URL拦截器的列表。

[信号] void QQmlEngine::warnings(const QList<QQmlError> &warnings)

当由QML生成警告消息时,将触发此信号。

相关非成员

enum QQmlModuleImportSpecialVersions

定义了一些可以传递给qmlRegisterModuleImport()和qmlUnregisterModuleImport()版本参数的特殊值。

常量描述
QQmlEngine::QQmlModuleImportModuleAny-1当作为基础模块的主版本传递时,表示导入应用于模块的任何版本。
QQmlEngine::QQmlModuleImportLatest-1当作为导入模块的主版本或副版本传递时,表示应导入整体最新或指定主版本的最新副版本。
QQmlEngine::QQmlModuleImportAuto-2当作为导入模块的主版本传递时,表示应转发基础模块的版本。

template <typename T> QObject *qmlAttachedPropertiesObject(const QObject *attachee, bool create = true)

此模板函数的形式为

template<typename T> QObject *qmlAttachedPropertiesObject(const QObject *attachee, bool create = true)

这返回被附加类型T附加到指定attachee的附加对象实例。

如果create为true且类型T是一个有效的附加类型,则创建并返回一个新的附加对象实例。

如果类型T不是一个有效的附加类型,或者如果create为false且attachee之前没有创建任何附加对象实例,则返回nullptr

另请参阅QML_ATTACHED()和提供附加属性

void qmlClearTypeRegistrations()

清除所有存储的类型注册,例如,使用qmlRegisterType()产生的注册信息。

在存在 QQmlEngine 或aiduò时,请不要调用此函数,否则行为将未定义。必须在调用此函数之前删除现有的 QQmlEngines。此函数仅影响应用程序全局缓存。删除 QQmlEngine 以清除与该引擎相关的所有缓存数据。

QQmlContext *qmlContext(const QObject *object)

返回关联到 objectQQmlContext(如果存在)。这等效于 QQmlEngine::contextForObject(object)。

注意:要在使用此函数之前添加 #include <QtQml> 报头。

另请参阅:contextForObject() 和 qmlEngine

QQmlEngine *qmlEngine(const QObject *object)

返回关联到 objectQQmlEngine(如果存在)。这等效于 QQmlEngine::contextForObject(object)->engine(),但更高效。

注意:要在使用此函数之前添加 #include <QtQml> 报头。

另请参阅:contextForObject() 和 qmlContext

bool qmlProtectModule(const char *uri, int majVersion)

该函数可保护模块免受进一步修改。这可以用于防止其他插件将类型注入到您的模块中。同时,这也可以提升性能,因为当达到此处导入时,它允许引擎跳过检查是否存在新类型或插件的可能性。

一旦调用 qmlProtectModule,QML 引擎将不再搜索新的 qmldir 文件来加载模块,但它将重用之前加载的任何 qmldir 文件。因此,这一点产生的类型仍然可以继续工作。请注意,不同的 QML 引擎可能加载不同的模块。然而模块保护是全局的,并影响所有引擎。在慢速文件系统中,定位文件和加载插件的开销可能会变得明显。因此,一旦确定不再需要加载模块,保护模块可以是一个非常好的优化。同时请注意,模块锁不仅影响插件,还影响任何其他 qmldir 指令(如 importprefer),以及在文件中声明的任何复合类型或脚本。

此外,在调用此函数之后,任何尝试将 C++ 类型注册到此 URI 和主版本组合的尝试都可能导致运行时错误。

如果找到以 uri 作为 模块标识符majVersion 作为主版本号的模块并将其锁定,则返回 true,否则返回 false。模块必须包含导出的类型才能找到。

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

此模板函数将 C++ 类型在 QML 系统中注册为匿名类型。生成的 QML 类型没有名称。因此,不能从 QML 系统创建此类型的实例。但是,您可以从作为其他类型的属性公开的实例访问此类型的实例。

当类型不会通过名称引用时,请使用此函数,特别是对于用作属性绑定左侧的 C++ 类型。要指明类型所属的模块,使用 uriversionMajor

例如,考虑以下两个类

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;
};

在QML中,我们将一个字符串分配给bar属性的baz

Foo {
    bar.baz: "abc"
    Component.onCompleted: print(bar.baz)
}

为了让QML引擎知道Bar类型有一个baz属性,我们必须让Bar为人所知

qmlRegisterType<Foo>("App", 1, 0, "Foo");
qmlRegisterAnonymousType<Bar>("App", 1);

由于在QML中实例化Foo类型,它必须使用带元素名的qmlRegisterType()版本注册

返回QML类型id。

另请参阅 QML_ANONYMOUS在C++和QML之间选择正确集成方法

模板 <typename T, typename E> int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)

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

返回QML类型id。

另请参阅 QML_EXTENDED()、qmlRegisterType()和注册扩展对象

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

这个模板函数使用从uri导入的库中名为qmlName的名称,在QML系统中注册C++类型及其扩展,其版本号由versionMajorversionMinor组成。

尽管这个类型有名称和类型,但无法创建它。如果用户尝试创建此类型的实例,将打印出具有给定reason的错误消息。

这在类型仅用于提供附加属性、枚举值或具有其扩展的抽象基类时很有用。

返回QML类型id。

另请参阅 QML_EXTENDED()、QML_UNCREATABLE()和qmlRegisterUncreatableType()。

void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)

这个函数在一个特定的uri上注册一个模块,在versionMajorversionMinor中指定版本。

这可以用来使某个模块版可用,即使没有为该版本注册类型。这在保持相关模块版本同步时特别有用。

void qmlRegisterModuleImport(const char *uri, int moduleMajor, const char *import, int importMajor = QQmlModuleImportLatest, int importMinor = QQmlModuleImportLatest)

注册模块uri的qmakeir-import,其主版本为moduleMajor

这与qmultir文件中的导入语句具有相同的效果:当导入moduleMajor版本的uri时,会自动导入 mniejsze warianty,包括importMajor. 如果 importMajorQQmlModuleImportLatest,则会导入该模块的最新版本,此时 importMinor 不重要。如果 importMinorQQmlModuleImportLatest,则会选择 importMajor 的最新次要版本。如果 importMajorQQmlModuleImportAuto,则导入的版本与 uri 正在导入的版本相同,此时 importMinor 不重要。如果 moduleMajorQQmlModuleImportModuleAny,则针对 uri 的任何主版本应用模块导入。例如,您可能指定,当任何版本的 MyModule 被导入时,应导入 MyOtherModule 的最新版本。那么,以下调用是合适的。

qmlRegisterModuleImport("MyModule", QQmlModuleImportModuleAny,
                        "MyOtherModule", QQmlModuleImportLatest);

或者,您可能指定,当导入 "MyModule" 的主版本 5 时,导入 "MyOtherModule" 的 3.14 版本。

qmlRegisterModuleImport("MyModule", 5, "MyOtherModule", 3, 14);

最后,如果您希望每次导入 "MyModule" 时都导入相同的 "MyOtherModule" 版本,请指定以下内容。

qmlRegisterModuleImport("MyModule", QQmlModuleImportModuleAny,
                        "MyOtherModule", QQmlModuleImportAuto);

另请参阅 qmlUnregisterModuleImport

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

这个模板函数使用从 uri 导入的库在 QML 系统中注册指定的 C++ 类型的特定版本,其版本号由 versionMajorversionMinor 组成。

返回QML类型id。

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

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

int qmlRegisterSingletonInstance(const char *uri, int versionMajor, int versionMinor, const char *typeName, QObject *cppObject)

此函数用于注册特定 uritypeName 的单例对象 cppObject。其版本由 versionMajorversionMinor 组成。

将单例类型安装到 URI 允许您不要求客户端为该类型创建单独实例,就为 QML 代码提供任意的功能(方法属性)。

使用此函数将给定类型 T 的对象注册为单例类型。

使用注册的单例类型名称可以引用 QObject 单例类型,这些名称可以用作Connections类型的目标,或作为任何其他类型 ID。然而,有一个例外:QObject 单例类型属性不能重命名,因为单例类型名称不能标识同一组件中任何其他项。

注意: cppObject 必须比使用它的 QML 引擎长命,并且 cppObject 必须具有与引擎相同的线程亲和力。如果您想为多个引擎创建单独的单例实例,则需要使用 qmlRegisterSingletonType。有关线程安全方面的更多信息,请参阅 线程和 QObjects

注意:qmlRegisterSingleton只能在所有该模块的类型都按程序方式进行注册时使用。

用法

// First, define your QObject which provides the functionality.
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;
};
// Second, create an instance of the object

// allocate example before the engine to ensure that it outlives it
QScopedPointer<SingletonTypeExample> example(new SingletonTypeExample);
QQmlEngine engine;

// Third, register the singleton type provider with QML by calling this
// function in an initialization function.
qmlRegisterSingletonInstance("Qt.example.qobjectSingleton", 1, 0, "MyApi", example.get());

为了在QML中使用已注册的单例类型,您必须导入对应版本的URI。

import QtQuick 2.0
import Qt.example.qobjectSingleton 1.0
Item {
    id: root
    property int someValue: MyApi.someProperty

    Component.onCompleted: {
        console.log(MyApi.doSomething())
    }
}

参见:QML_SINGLETONqmlRegisterSingletonType.

int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, std::function<QJSValue> (QQmlEngine *, QJSEngine *)> callback)

此函数可用于在特定uritypeName中注册单例类型提供程序callback,版本由versionMajorversionMinor指定。

安装单例类型允许开发者向客户端提供任意功能(方法和属性),而无需客户端实例化类型的单个实例。

单例类型可以是QObjectQJSValue。此函数应用于注册返回QJSValue的单例类型的单例类型提供程序函数。

注意:如果改变QJSValue单例类型属性,将不会触发绑定重新评估。

用法

// First, define the singleton type provider function (callback).
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;
}

// Second, register the singleton type provider with QML by calling this function in an initialization function.
qmlRegisterSingletonType("Qt.example.qjsvalueApi", 1, 0, "MyApi", example_qjsvalue_singletontype_provider);

或者,您可以使用C++11 lambda

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;
});

要使用在QML中注册的单例类型,您必须导入单例类型。

import QtQuick 2.0
import Qt.example.qjsvalueApi 1.0 as ExampleApi
Item {
    id: root
    property int someValue: ExampleApi.MyApi.someProperty
}

参见:QML_SINGLETON选择C++和QML之间正确的集成方法.

template <typename T> int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName, std::function<QObject> *(QQmlEngine *, QJSEngine *)> callback)

此函数可用于在特定uritypeName中注册单例类型提供程序callback,版本由versionMajorversionMinor指定。

将单例类型安装到URI中允许开发者向客户端提供任意功能(方法和属性),而无需客户端实例化类型的单个实例。

单例类型可以是QObjectQJSValue。此函数应用于注册返回给定类型T的QObject的单例类型提供程序函数。

可以通过在注册时所使用的类型名称来引用QObject单例类型,并可以使用此类型名称作为Connections类型的目标或其他类型id使用。此例外的例外是,QObject单例类型属性不能被别名。

注意:单例类型提供程序返回的QObject单例类型实例由QML引擎所有,除非对象已显式设置QQmlEngine::CppOwnership标志。

用法

// First, define your QObject which provides the functionality.
class SingletonTypeExample : public QObject
{
    Q_OBJECT
    Q_PROPERTY (int someProperty READ someProperty WRITE setSomeProperty NOTIFY somePropertyChanged)

public:
    SingletonTypeExample(QObject *parent = nullptr)
        : QObject(parent), m_someProperty(0)
    {
    }

    ~SingletonTypeExample() {}

    Q_INVOKABLE int doSomething() { setSomeProperty(5); return m_someProperty; }

    int someProperty() const { return m_someProperty; }
    void setSomeProperty(int val) { m_someProperty = val; emit somePropertyChanged(val); }

signals:
    void somePropertyChanged(int newValue);

private:
    int m_someProperty;
};

// Second, define the singleton type provider function (callback).
static QObject *example_qobject_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
    Q_UNUSED(engine)
    Q_UNUSED(scriptEngine)

    SingletonTypeExample *example = new SingletonTypeExample();
    return example;
}

// Third, register the singleton type provider with QML by calling this function in an initialization function.
qmlRegisterSingletonType<SingletonTypeExample>("Qt.example.qobjectSingleton", 1, 0, "MyApi", example_qobject_singletontype_provider);

或者,您可以使用C++11 lambda

qmlRegisterSingletonType<SingletonTypeExample>("Qt.example.qobjectSingleton", 1, 0, "MyApi", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
    Q_UNUSED(engine)
    Q_UNUSED(scriptEngine)

    SingletonTypeExample *example = new SingletonTypeExample();
    return example;
});

要使用在QML中注册的单例类型,您必须导入单例类型。

import QtQuick 2.0
import Qt.example.qobjectSingleton 1.0
Item {
    id: root
    property int someValue: MyApi.someProperty

    Component.onCompleted: {
        someValue = MyApi.doSomething()
    }
}

参见:QML_SINGLETON选择C++和QML之间正确的集成方法.

int qmlRegisterSingletonType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)

此功能可用于以名称 qmlName 注册单例类型,在从具有版本号由 versionMajorversionMinor 组成的 uri 导入的库中。该类型由位于 url 的 QML 文件定义。URL 必须是绝对 URL,即 url.isRelative() == false。

此外,类型的 QML 文件必须在它的导入语句中包含 pragma Singleton 语句。

单例类型可以通过其注册的类型名称进行引用,并且此类型名称可以用作 Connections 类型的目标或用于任何其他类型 ID。一个例外是,单例类型属性可能不能重命名(因为单例类型名称不能识别与其他任何项相同的组件内的对象)。

用法

// First, define your QML singleton type which provides the functionality.
pragma Singleton
import QtQuick 2.0
Item {
    property int testProp1: 125
}
// Second, register the QML singleton type by calling this function in an initialization function.
qmlRegisterSingletonType(QUrl("file:///absolute/path/SingletonType.qml"), "Qt.example.qobjectSingleton", 1, 0, "RegisteredSingleton");

要使用在QML中注册的单例类型,您必须导入单例类型。

import QtQuick 2.0
import Qt.example.qobjectSingleton 1.0
Item {
    id: root
    property int someValue: RegisteredSingleton.testProp1
}

还可以不使用 qmlRegisterSingletonType 函数而注册 QML 单例类型。这可以通过在类型的 QML 文件的导入语句中添加 pragma Singleton 语句来完成。此外,类型必须在具有单例关键字的 qmldir 文件中定义,并且 qmldir 必须由使用单例的 QML 文件导入。

另请参阅 QML_SINGLETON.

template <typename T> int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)

此模板函数将在 QML 系统中注册 C++ 类型,并使用名称 qmlName,在从 uri 导入的库中,该版本号由 versionMajorversionMinor 组成。

返回QML类型id。

此模板函数有两种形式

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);

前者是标准形式,用于注册类型 T 为一个新类型。后者允许将类的特定修订版在指定版本中注册(参见 类型修订和版本)。

例如,此代码将 C++ 类 MySliderItem 注册为名为 Slider 的 QML 类型,属于版本为 1.0 的类型命名空间 "com.mycompany.qmlcomponents"。

qmlRegisterType<MySliderItem>("com.mycompany.qmlcomponents", 1, 0, "Slider");

注册后,类型可以使用指定的类型命名空间和版本号在 QML 中使用。

import com.mycompany.qmlcomponents 1.0

Slider {
    // ...
}

请注意,库为比实际库版本更旧的版本注册类型是完全合理的。实际上,新库通常允许之前版本编写的 QML 继续工作,即使有一些类型的更高级版本可用。

另请参阅 QML_ELEMENTQML_NAMED_ELEMENT(),以及 在 C++ 和 QML 之间选择正确的集成方法

int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName)

此函数在 QML 系统中注册具有名称 qmlName 的类型,在从 uri 导入的库中,该版本号由 versionMajorversionMinor 组成。该类型由位于 url 的 QML 文件定义。URL 必须是绝对 URL,即 url.isRelative() == false。

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

如果注册失败,则返回 -1。

int qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString &message)

此函数在QML系统中注册一个名为qmlName的类型,该类型来自uri导入的类型命名空间,其版本号由versionMajorversionMinor组成,但任何尝试实例化该类型的尝试都将产生给定的错误message

通常,插件导出的类型应该是固定的。但是,如果一个C++类型不可用,你应该至少“保留”QML类型名称,并向不可用的类型用户提供一个有意义的错误信息。

返回QML类型id。

示例

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

这将导致任何导入"MinehuntCore"类型命名空间并尝试使用该类型的QML产生一个错误信息

fun.qml: Get back to work, slacker!
   Game {
   ^

否则,会给出通用的“游戏不是一个类型”的信息。

另请参阅 QML_UNAVAILABLEqmlRegisterUncreatableType(),以及在C++和QML之间选择正确的集成方法

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

此函数在QML系统中以从uri导入的库中的名称qmlName注册指定的staticMetaObject及其扩展。

不能创建元实例。如果用户尝试创建它,将打印出带有给定reason的错误信息。

此函数用于注册Q_NAMESPACE命名空间。

返回QML类型id。

例如

namespace MyNamespace {
  Q_NAMESPACE
  enum MyEnum {
      Key1,
      Key2,
  };
  Q_ENUM_NS(MyEnum)
}

//...
qmlRegisterUncreatableMetaObject(MyNamespace::staticMetaObject, "io.qt", 1, 0, "MyNamespace", "Access to enums & flags only");

在QML方面,你现在可以使用注册的枚举

Component.onCompleted: console.log(MyNamespace.Key2)

另请参阅 QML_ELEMENTQML_NAMED_ELEMENT()以及QML_UNCREATABLE

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

此模板函数将在 QML 系统中注册 C++ 类型,并使用名称 qmlName,在从 uri 导入的库中,该版本号由 versionMajorversionMinor 组成。

虽然该类型有一个名称和一个类型,但它不能被创建,如果尝试创建,则会给出给定的错误message

这在只打算提供附加属性或枚举值的地方很有用。

返回QML类型id。

另请参阅 QML_UNCREATABLEqmlRegisterTypeNotAvailable以及在C++和QML之间选择正确的集成方法

int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)

返回具有在特定uri中注册并具有在versionMajorversionMinor中指定的版本的名称qmlName的类型ID。

此函数返回与QML类型注册函数如qmlRegisterType() 和qmlRegisterSingletonType()类似的值。

如果qmlNameuriversionMajor与已注册的类型匹配,但指定在versionMinor中的次要版本更高,则返回最接近次要版本的类型的ID。

如果未找到匹配的类型或提供的参数之一无效,则返回-1。

另请参阅QML_ELEMENTQML_NAMED_ELEMENTQML_SINGLETONqmlRegisterType() 和 qmlRegisterSingletonType().

void qmlUnregisterModuleImport(const char *uri, int moduleMajor, const char *import, int importMajor = QQmlModuleImportLatest, int importMinor = QQmlModuleImportLatest)

删除先前使用qmlRegisterModuleImport()注册的模块导入。

调用此函数可确保当使用moduleMajor版本的uri时,不会自动导入版本importMajor.importMinorimport。版本解析的方式与qmlRegisterModuleImport()相同。

另请参阅qmlRegisterModuleImport().

宏文档

QML_ADDED_IN_VERSION(版本主号, 版本次号)

声明所包围的类型或命名空间是在指定的版本主号.版本次号版本中添加的。版本假定与在方法、槽或信号上由Q_REVISION()宏给出的任何修订一致,并在使用Q_PROPERTY()声明的属性上的任何REVISION()属性一致。

只有当类型或命名空间由于其具有QML_ELEMENTQML_NAMED_ELEMENT()、QML_ANONYMOUSQML_INTERFACE宏而可在QML中使用时,QML_ADDED_IN_VERSION()才有效。

如果类型所属的QML模块的导入版本低于通过此方式确定的版本,则QML类型不可见。

另请参阅QML_ELEMENTQML_NAMED_ELEMENT.

QML_ANONYMOUS

声明所包围的类型对QML可用,但在QML中是匿名的。此类型无法在QML中创建或用于声明属性,但可以从C++传递时被识别。在QML中,如果此类属性已在C++中声明,则可以使用该类型的属性。

另请参阅QML_ELEMENTQML_NAMED_ELEMENTQML_UNCREATABLEQML_INTERFACE.

QML_ATTACHED(附加类型)

声明所包围的类型将附加类型作为附加属性附加到其他类型。如果在用QML_ELEMENTQML_NAMED_ELEMENT()宏暴露给QML的类型上生效。

注意:类名需要完全限定,即使你已经在命名空间内部。

另请参阅QML_ELEMENTQML_NAMED_ELEMENTqmlAttachedPropertiesObject提供附加属性

[自6.5起] QML_CONSTRUCTIBLE_VALUE

将周围的数据类型标记为可构造的。这意味着,任何类型的数据构造函数(带有恰好一个参数)都可以在将JavaScript值分配给此类属性时使用。

您可以按以下方式声明可构造值类型:

class MyValueType
{
    Q_GADGET
    QML_VALUE_TYPE(myValueType)
    QML_CONSTRUCTIBLE_VALUE
public:
    Q_INVOKABLE MyValueType(double d);

    // ...
};

使用上述类型,以下QML代码将使用给定的构造函数生成一个MyValueType值,并将其分配给属性。

QtObject {
    property myValueType v: 5.4
}

您也可以这样构造一组值

QtObject {
    property list<myValueType> v: [5.4, 4.5, 3.3]
}

如果您使值类型可寻址,则可以使用此类类型在类型断言中显式构造它

pragma ValueTypeBehavior: Addressable

QtObject {
    function process(d: real) {
        let v = d as myValueType;
        // v is a myValueType now, not a number
    }
}

此宏是在Qt 6.5中引入的。

另请参阅 QML_VALUE_TYPE.

QML_DECLARE_TYPE

等同于Q_DECLARE_METATYPE(TYPE *)Q_DECLARE_METATYPE(QQmlListProperty')

QML_DECLARE_TYPEINFO(类型, 标志)

声明给定的类型的附加属性,如指定的标志所述。

目前唯一支持的类型信息是QML_HAS_ATTACHED_PROPERTIES,它声明类型支持附加属性。如果类型包含QML_ATTACHED宏,则无需使用QML_DECLARE_TYPEINFO()。

QML_ELEMENT

使用类的或命名空间的名字作为QML元素的名称,声明包装类型或命名空间在QML中可用。

例如,这使得C++类Slider作为名为Slider的QML类型可用。它的所有属性、可调用方法和枚举都公开。

class Slider : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged FINAL)
    // ...
public:
    enum Slippiness {
        Dry, Wet, Icy
    };
    Q_ENUM(Slippiness)

    Q_INVOKABLE void slide(Slippiness slippiness);

    // ...
}

您可以使用构建系统将该类型注册在名为com.mycompany.qmlcomponents的类型命名空间中,大版本号为1。对于qmake,在您的项目文件中指定以下内容:

CONFIG += qmltypes
QML_IMPORT_NAME = com.mycompany.qmlcomponents
QML_IMPORT_MAJOR_VERSION = 1

对于CMake,将URI和版本传递给qt_add_qml_module

qt6_add_qml_module(myapp
  URI com.mycompany.qmlcomponents
  VERSION 1.0
)

一旦注册,就可以使用与相同的类型命名空间和版本号导入的类型在QML中使用

import com.mycompany.qmlcomponents 1.0

Slider {
    value: 12
    Component.onCompleted: slide(Slider.Icy)

    // ...
}

您还可以通过这种方式使带有Q_NAMESPACE标签的命名空间可用,以公开它们包含的任何带有Q_ENUM_NS标签的枚举

namespace MyNamespace {
  Q_NAMESPACE
  QML_ELEMENT

  enum MyEnum {
      Key1,
      Key2,
  };
  Q_ENUM_NS(MyEnum)
}

在QML中,您可以然后使用枚举

Component.onCompleted: console.log(MyNamespace.Key2)

注意:当类具有相同的名称但位于不同的命名空间中时,使用QML_ELEMENT在两者上都会导致冲突。请确保其中一个使用QML_NAMED_ELEMENT()。

注意:类名需要完全限定,即使你已经在命名空间内部。

另请参阅 在C++和QML之间选择正确的集成方法QML_NAMED_ELEMENT(), Q_REVISION(),和QML_ADDED_IN_VERSION()。

QML_EXTENDED(EXTENDED_TYPE)

声明包含类型使用EXTENDED_TYPE作为扩展来提供更多属性、方法和枚举(在QML中)。如果类型使用QML_ELEMENTQML_NAMED_ELEMENT()宏暴露给QML,则此声明生效。

警告:EXTENDED_TYPE的成员被隐式处理为FINAL。

注意:类名需要完全限定,即使你已经在命名空间内部。

另请参阅 QML_ELEMENTQML_NAMED_ELEMENT(), QML_EXTENDED_NAMESPACE(),和注册扩展对象

QML_EXTENDED_NAMESPACE(EXTENDED_NAMESPACE)

声明包含的类型使用EXTENDED_NAMESPACE作为扩展来在QML中提供更多枚举。如果类型使用QML_ELEMENTQML_NAMED_ELEMENT()宏暴露给QML,这将生效。枚举需要向元对象系统公开,才能使其工作。

例如,以下C++代码

namespace MyNamespace {
    Q_NAMESPACE
    enum MyEnum { MyEnumerator = 10 };
    Q_ENUM_NS(MyEnum)
}

class QmlType : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_EXTENDED_NAMESPACE(MyNamespace)
}

我们可以在QML中访问枚举

QmlType {
    property int i: QmlType.MyEnumerator // i will be 10
}

注意:EXTENDED_NAMESPACE也可以是一个QObject或QGadget;在这种情况下,与QML_EXTENDED(它也公开了方法和属性)相比,只公开了其枚举。

注意:EXTENDED_NAMESPACE必须有一个元对象;换句话说,它必须是包含Q_NAMESPACE宏的命名空间或QObject/QGadget。

注意:类名需要完全限定,即使你已经在命名空间内部。

另请参阅:QML_ELEMENTQML_NAMED_ELEMENT()、QML_EXTENDED注册扩展对象Q_ENUMQ_ENUM_NS

QML_EXTRA_VERSION(MAJOR, MINOR)

声明类型还应在版本MAJOR.MINOR中可用。如果类型应该可用于多个主要版本,这可能很有用。

类型将自动注册为

值得注意的是,它们不会自动注册在上述内容之间的任何旧版主版本中。您可以使用QML_EXTRA_VERSION手动在更多主版本中注册您的类型。

注意:保留多个旧版主版本在计算上成本较高。

另请参阅:QML_ELEMENTQML_ADDED_IN_VERSION

QML_FOREIGN(FOREIGN_TYPE)

声明在包含的C++类型中的任何QML_ELEMENTQML_NAMED_ELEMENT()、QML_ANONYMOUSQML_INTERFACEQML_UNCREATABLE()、QML_SINGLETONQML_ADDED_IN_VERSION()、QML_ADDED_IN_MINOR_VERSION()、QML_REMOVED_IN_MINOR_VERSION()、QML_EXTENDED()或QML_EXTENDED_NAMESPACE()宏都不适用于包含的类型,而应适用于FOREIGN_TYPE。包含的类型仍然需要使用Q_GADGETQ_OBJECT宏与元对象系统注册。

这对于注册无法添加宏的类型很有用,例如它们属于第三方库。要注册命名空间,请参阅QML_FOREIGN_NAMESPACE

注意:您可能想使用 QML_NAMED_ELEMENT() 代替 QML_ELEMENT。在使用 QML_ELEMENT 的场景中,元素被命名为包含它的结构名称,而不是外部类型名称。《Foreign objects integration》这章在《Writing advanced QML Extensions with C++》中演示了这一点。

注意:QML_ATTACHED() 目前不能像这样重定向。必须在实现 qmlAttachedProperties() 的同一类型中指定。

注意:类名需要完全限定,即使你已经在命名空间内部。

也参见:QML_ELEMENTQML_NAMED_ELEMENT() 和 QML_FOREIGN_NAMESPACE

QML_FOREIGN_NAMESPACE(FOREIGN_NAMESPACE)

声明在包含的 C++ 命名空间中定义的任何 QML_ELEMENTQML_NAMED_ELEMENTQML_ANONYMOUSQMLINTERFACEQML_UNCREATABLEQML_SINGLETONQML_ADDED_IN_VERSIONQML_ADDED_IN_MINOR_VERSIONQML_REMOVED_IN_MINOR_VERSION() 宏不适用于包含类型,而是适用于 FOREIGN_NAMESPACE。包含的命名空间仍需要使用 Q_NAMESPACE 宏在 meta object system 中注册。

这对于注册无法添加宏的命名空间很有用,例如,因为它们属于第三方库。

也参见:QML_ELEMENTQML_NAMED_ELEMENTQML_FOREIGN

QML_IMPLEMENTS_INTERFACES(interfaces)

此宏告诉 Qt 类实现了哪些 QML interfaces。此宏应仅用于使用 QML INTERFACE 的类进行接口编程,否则应使用 Q_INTERFACES。其是 QML 通过 QML_ELEMENT 进行声明注册正确工作所必需的。

也参见:QMLINTERFACEQ_INTERFACES

QMLINTERFACE

此宏将包含的 C++ 类型在 QML 系统中注册为接口。

在 QML 中注册为接口的类型也应使用 meta object system 声明自己为接口。例如

struct FooInterface
{
    QML_INTERFACE
public:
    virtual ~FooInterface();
    virtual void doSomething() = 0;
};

Q_DECLARE_INTERFACE(FooInterface, "org.foo.FooInterface")

以这种方式注册到 QML 中后,它们可以用作属性类型

Q_PROPERTY(FooInterface *foo READ foo WRITE setFoo)

当您将 QObject 子类分配给此属性时,QML 引擎会自动进行接口转换到 FooInterface*

接口类型在 QML 中是隐式匿名和不可创建的。

注意:在从使用 QMLINTERFACE 的类型继承时,请使用 QML_IMPLEMENTS_INTERFACES 而不是 Q_INTERFACES

也参见:QML_IMPLEMENTS_INTERFACESQML_ELEMENTQML_NAMED_ELEMENTQML_UNCREATABLEQML_ANONYMOUS

QML_NAMED_ELEMENT(name)

使用 name 作为元素名称,声明包围的类型或命名空间在 QML 中可用。否则与 QML_ELEMENT 的行为相同。

class SqlEventDatabase : public QObject
{
    Q_OBJECT
    QML_NAMED_ELEMENT(EventDatabase)

    // ...
};

另见 选择 C++ 和 QML 之间的正确集成方法QML_ELEMENT

QML_REMOVED_IN_VERSION(MAJOR, MINOR)

声明在指定的 MAJOR.MINOR 版本中已删除包围的类型或命名空间。这在替换 QML 类型的实现时非常有用。如果同一 QML 名称的不同类型或命名空间存在相应的 QML_ADDED_IN_VERSION(),则在导入低于 MAJOR.MINOR 的模块版本时使用已删除的类型,在导入大于或等于 MAJOR.MINOR 的模块版本时使用添加的类型。

只有当类型或命名空间在 QML 中可用,通过有 QML_ELEMENTQML_NAMED_ELEMENT()、QML_ANONYMOUSQML_INTERFACE 宏时,QML_REMOVED_IN_VERSION() 才会生效。

另请参阅QML_ELEMENTQML_NAMED_ELEMENT.

QML_SEQUENTIAL_CONTAINER(VALUE_TYPE)

此宏声明包围或引用的类型作为管理一系列 VALUE_TYPE 元素的顺序容器。VALUE_TYPE 可以是一个实际的 值类型 或指向 对象类型 的指针。由于容器通常是模板,您很少能够将此宏添加到实际的容器声明中。您应该使用 QML_FOREIGN 将类型注册附加到模板实例化。使用此技术,您可以为以下数据声明如序列容器

class IntDequeRegistration
{
  Q_GADGET
  QML_FOREIGN(std::deque<int>)
  QML_ANONYMOUS
  QML_SEQUENTIAL_CONTAINER(int)
};

在此之后,您可以在 QML 中将其用作类似 JavaScript 数组的容器。

class Maze
{
  Q_OBJECT
  Q_ELEMENT
  // 0: North, 1: East, 2: South, 3: West
  Q_PROPERTY(std::deque<int> solution READ solution CONSTANT FINAL)
  [...]
}
Item {
  Maze {
    id: maze
  }

  function showSolution() {
      maze.solution.forEach([...])
  }
}

注意:对于 QML 值类型,自动注册为顺序容器的有 QList。对于 QML 对象类型,有 QQmlListProperty。您不必添加这些注册。

注意:您目前无法给容器指定自定义名称。传递给 QML_NAMED_ELEMENT 的任何参数都将被忽略。自动注册的顺序容器在熟悉的 list<...> 名称下可用,例如 list<QtObject>list<font>

注意:类名需要完全限定,即使你已经在命名空间内部。

另见 QML_ANONYMOUSQML_FOREIGN

QML_SINGLETON

在QML中声明封装的类型为单例。只有当类型是Q_OBJECT且在QML中可用(通过拥有QML_ELEMENTQML_NAMED_ELEMENT()宏)时才有效。默认情况下,每个QQmlEngine在第一次访问该类型时,将尝试使用该类型的默认构造函数或签名为T *create(QQmlEngine *, QJSEngine *)的静态工厂函数创建单例实例。如果两者都存在且可访问,则首选默认构造函数。如果没有默认构造函数,也没有工厂函数,则单例不可访问。QML引擎通常假定对单例的所有权,并在引擎本身被销毁时删除它。您可以通过在单例上调用QJSEngine::setObjectOwnership()来防止这种情况。

要声明默认可构造的类为单例,只需添加QML_SINGLETON即可。

class MySingleton : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_SINGLETON
    // Q_PROPERTY( ... )
public:
    // members, Q_INVOKABLE functions, etc.
};

如果单例类不是默认可构造的,但可以修改它,可以向其中添加工厂函数,以便使其可访问。

class MySingleton : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_SINGLETON
    // Q_PROPERTY( ... )

public:
    static MySingleton *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
    {
        MySingleton *result = nullptr;
        // Create the object using some custom constructor or factory.
        // The QML engine will assume ownership and delete it, eventually.
        return result;
    }

    // members, Q_INVOKABLE functions, etc
};

如果不能修改类且它没有默认构造函数或合适的工厂函数,可以提供一个QML_FOREIGN包装器来定义工厂函数。

struct SingletonForeign
{
    Q_GADGET
    QML_FOREIGN(MySingleton)
    QML_SINGLETON
    QML_NAMED_ELEMENT(MySingleton)
public:

    static MySingleton *create(QQmlEngine *, QJSEngine *engine)
    {
        MySingleton *result = nullptr;
        // Create the instance using some custom constructor or factory.
        // The QML engine will assume ownership and delete it, eventually.
        return result;
    }
};

最后,如果您想要提供一个不能控制的特定单例对象,可以从中返回工厂函数创建,这将替代qmlRegisterSingletonInstance函数。如果您调用

qmlRegisterSingletonInstance("MyModule", 1, 0, "MySingleton", myObject);

其中myObject是类型MySingleton *,可以这样做

struct SingletonForeign
{
    Q_GADGET
    QML_FOREIGN(MySingleton)
    QML_SINGLETON
    QML_NAMED_ELEMENT(MySingleton)
public:

    // Initialize this using myObject where you would previously
    // call qmlRegisterSingletonInstance().
    inline static MySingleton *s_singletonInstance = nullptr;

    static MySingleton *create(QQmlEngine *, QJSEngine *engine)
    {
        // The instance has to exist before it is used. We cannot replace it.
        Q_ASSERT(s_singletonInstance);

        // The engine has to have the same thread affinity as the singleton.
        Q_ASSERT(engine->thread() == s_singletonInstance->thread());

        // There can only be one engine accessing the singleton.
        if (s_engine)
            Q_ASSERT(engine == s_engine);
        else
            s_engine = engine;

        // Explicitly specify C++ ownership so that the engine doesn't delete
        // the instance.
        QJSEngine::setObjectOwnership(s_singletonInstance,
                                      QJSEngine::CppOwnership);
        return s_singletonInstance;
    }

private:
    inline static QJSEngine *s_engine = nullptr;
};

这样,现有的类MySingleton被声明为一个名为MySingleton的QML单例。您可以在使用之前设置任何实例为s_singletonInstance成员。这一切无需修改MySingleton本身。

注意:如果单例被多个QML引擎访问,或者访问它的QML引擎与单例对象自身有不同的线程相关性,则此模式不起作用。如上所示,可以通过检查create()方法的参数来确认引擎的标识和线程相关性。

另请参阅:QML_ELEMENTQML_NAMED-elementqmlRegisterSingletonInstanceQQmlEngine::singletonInstance,以及QML中的单例

[自6.5以来] QMLStructuredValue

将周围的值类型标记为结构化。结构化值类型可以从JavaScript对象逐个属性地构建,并且首选。但结构化值类型也始终是QML_CONSTRUCTIBLE_VALUE。这意味着您仍然可以提供Q_INVOKABLE构造函数以处理从原始类型构建。

您可以按以下方式声明结构化值类型

class MyValueType
{
    Q_GADGET
    QML_VALUE_TYPE(myValueType)
    QML_STRUCTURED_VALUE
    Q_PROPERTY(double d READ d WRITE setD)
    Q_PROPERTY(string e READ e WRITE setE)

    // ...
};

然后您可以按以下方式填充此类型的属性

QtObject {
    property myValueType v: ({d: 4.4, e: "a string"})
}

额外的括号是必要的,以消除JavaScript对象与可能被解释为JavaScript代码块的歧义。

您也可以这样构造一组值

QtObject {
    property list<myValueType> v: [
        {d: 4.4, e: "a string"},
        {d: 7.1, e: "another string"}
    ]
}

如果您使值类型可寻址,则可以使用此类类型在类型断言中显式构造它

pragma ValueTypeBehavior: Addressable

QtObject {
    function process(d: real) {
        let v = {d: d, e: objectName} as myValueType;
        // v is a myValueType now
    }
}

此宏是在Qt 6.5中引入的。

另请参阅:QML_VALUE_TYPEQML_CONSTRUCTIBLE_VALUE

QMLUnavailable

此宏将封装的类型标记为在QML中不可用。它注册了一个内部空类型,称为QQmlTypeNotAvailable,作为QML_FOREIGN()类型,并使用您指定的任何进一步QML宏。

通常,模块导出的类型应该是固定的。然而,如果某个C++类型不可用,您至少应该“保留”QML类型的名称,并为不可用的类型用户提供有意义的错误信息。

示例

#ifdef NO_GAMES_ALLOWED
struct MinehuntGame
{
    Q_GADGET
    QML_NAMED_ELEMENT(Game)
    QML_UNAVAILABLE
    QML_UNCREATABLE("Get back to work, slacker!");
};
#else
class MinehuntGame : public QObject
{
    Q_OBJECT
    QML_NAMED_ELEMENT(Game)
    // ...
};
#endif

这将导致任何尝试使用“游戏”类型的QML产生错误信息。

fun.qml: Get back to work, slacker!
   Game {
   ^

使用此技术,您只需要一个Q_GADGET结构来自定义错误信息,而不需要一个完整的QObject。如果没有QML_UNCREATABLE,QML_UNAVAILABLE仍然比通常对完全未知类型的“不是类型”错误信息更具体。

注意:类名需要完全限定,即使你已经在命名空间内部。

另请参阅QML_ELEMENTQML_NAMED_ELEMENT()、QML_UNCREATABLEQML_FOREIGN

QML_UNCREATABLE(原因)

声明封装的类型不能从QML创建。如果类型在QML中可用,则通过具有QML_ELEMENTQML_NAMED_ELEMENT()宏来生效。如果检测到尝试从QML创建类型,原因将被作为错误信息发出。

某些QML类型是隐式不可创建的,特别是那些使用QML_ANONYMOUS或使用QML_ELEMENTQML_NAMED_ELEMENT()暴露的命名空间。

自从Qt 6.0以来,您可以使用空字符串而不是原因,以使用标准消息。

另请参阅QML_ELEMENTQML_NAMED_ELEMENTQML_ANONYMOUS

QML_VALUE_TYPE(名称)

声明封装的类型或命名空间在QML中可用,使用名称作为名称。类型必须是值类型,名称必须是小写。

class MyValueType
{
    Q_GADGET
    QML_VALUE_TYPE(myValueType)

    // ...
};

另请参阅在C++和QML之间选择正确的集成方法QML_NAMED_ELEMENT

© 2024 Qt公司有限公司。本文件中包含的文档贡献是各自所有者的版权。所提供的文档是根据自由软件基金会发布的GNU自由文档许可证版本1.3的条款许可的。Qt及其标志是芬兰及/或世界其他地区的Qt公司有限公司的商标。所有其他商标均为其各自所有者的财产。