本页内容

将 QML 模块移植到 CMake

在 Qt 6 中,Qml 模块变得更加强大且易于使用。以下各节介绍了如何将 Qml 模块移植到qt_add_qml_moduleCMake API。

另请参阅《QML 模块现代化》,了解如何对已使用qt_add_qml_module 的 QML 模块进行现代化改造。

识别需要修复的问题

请使用qmllint辅助完成此过程。

每个使用`qt_add_qml_module` 定义的 QML 模块都有一个 `_qmllint ` CMake 目标,您可以利用它来识别潜在的问题或改进之处。例如,对于名为 `MyQmlLibrary ` 的 QML 模块,请使用 `MyQmlLibrary_qmllint`。若要对所有 QML 模块运行`qmllint`,请使用 `all_qmllint`。

qmllint中提示 QML 模块问题的警告类别包括:

为 qt_add_qml_module 准备项目

在 CMake 中启用 qt_add_qml_module

要在 CMake 中启用qt_add_qml_module,请在项目顶级CMakeLists.txt 文件中的find_package 调用中添加Core 和Qml :

find_package(Qt6 REQUIRED COMPONENTS Core Qml)

使用 qt_standard_project_setup

qt_standard_project_setup除了其他功能外,还会设置qt_add_qml_module 所需的Qt CMake 策略。

在项目顶级CMakeLists.txt 文件中,在任何qt_add_qml_module调用之前调用qt_standard_project_setup:

qt_standard_project_setup(REQUIRES 6.8)

使用 qt_add_qml_module

qt_add_qml_module是负责生成 QML 模块的 CMake 函数。它会自动生成qmldir 和qmltypes 文件,并配置qmlcachegen或qmllint 等工具。

在 CMake 中,QML 模块既可以添加到可执行目标,也可以添加到库目标。附加到可执行目标的 QML 模块无法被其他可执行文件使用或链接,而附加到库目标的 QML 模块则可以。

将 QML 模块添加到可执行目标

在这种情况下,QML 模块的源文件将被视为可执行文件本身的一部分,而非编译成独立的库。这意味着不会为此模块创建模块或插件库——该模块已完全集成到可执行文件中。 因此,该模块与该特定程序绑定,无法被其他可执行文件或库重复使用。

要在可执行文件中添加 QML 模块,请在您的 `CMakeLists.txt` 中:

# pre-existing:
qt_add_executable(MyApp main.cpp)

# add this
qt_add_qml_module(MyApp
    URI MyAppModule
    QML_FILES
        Main.qml # and possibly more .qml files
)

Main.qml 应以大写字母开头,以便通过loadFromModule 方法(如QQmlApplicationEngine::loadFromModule 或QQmlComponent::loadFromModule )进行实例化。此外,QML 模块的 URI 应与目标名称不同,以避免在构建文件夹中发生名称冲突。

将 QML 模块添加到库目标中

要将 QML 模块添加到您的库中,请在您的 `CMakeLists.txt` 文件中:

qt_add_qml_module(MyQmlLibrary
    URI MyQmlModule
    QML_FILES MyQmlComponent1.qml MyQmlComponent2.qml...
    SOURCES MyCppComponent1.h MyCppComponent1.cpp MyCppComponent2.h MyCppComponent2.cpp...
    RESOURCES MyResource1.png MyResource2.png...
)

如果MyQmlLibrary 目标尚不存在(如本例所示),qt_add_qml_module将通过qt_add_library创建一个SHARED 库。

注意:您的 QML 模块 URI 应与目标名称不同,以避免在构建文件夹中发生名称冲突。

使用 loadFromModule 加载您的 QML 文件

使用 `loadFromModule ` 加载您的 QML 文件,例如:

engine.load(QUrl(QStringLiteral("qrc:/MyQmlModule/Main.qml")));
// becomes
engine.loadFromModule("MyQmlModule", "Main");

删除手动编写的 qmldir 文件

qt_add_qml_module会自动生成qmldir 文件。如果您的qmldir 中包含单例,请在调用qt_add_qml_module之前,在CMakeLists.txt 中使用以下方式声明它们:

set_source_files_properties(MySingleton.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)

之后请删除手动编写的qmldir 文件。

删除由 qmlplugindump 生成的 qmltypes 文件

当所有类型均采用声明式类型注册时,qt_add_qml_module会自动生成qmltypes 文件,从而无需再使用qmlplugindump 等工具手动生成qmltypes 文件。

要实现这一点,请移除对qmlRegisterType 及其变体的手动调用。然后,使用QML_ELEMENT以声明式方式注册您的类型,例如:

// add this header
#include <QtQml/qqmlregistrations.h>

class MyComponent: public QObject {
    Q_OBJECT

    // add this line to register MyComponent as 'MyComponent' in QML.
    QML_ELEMENT
    ....
};

有关如何处理更复杂的注册情况(如外部类型的注册),请参阅《使用 QML 类型系统注册 C++ 类型》。

之后,请删除手动编写的qmltypes 文件。

移除手动编写的类型注册插件

qt_add_qml_module可以为您自动生成一个QML 模块插件。如果您的插件唯一任务是进行类型注册,则无需手动编写插件。如果切换到声明式类型注册后,插件中的所有代码均已被移除,请彻底删除该插件。

请确保从qt_add_qml_module 中移除 NO_PLUGIN 、NO_PLUGIN_OPTIONAL 、NO_CREATE_PLUGIN_TARGET 和NO_GENERATE_PLUGIN_SOURCE 参数,以允许自动生成插件。

删除 qrc 文件

qt_add_qml_module会自动生成qrc 文件。若要在qrc 文件中列出资源(如图像或声音文件),请将其添加到qt_add_qml_module 的 RESOURCES 参数中。您可以在:/qt/qml/MyQmlLibraryModule/ 下找到该模块的资源。

将目录导入替换为 QML 模块导入

将目录导入替换为 QML 模块导入。例如:

import "content" // contains SomeType.qml
// becomes
import MyQmlModule // contains SomeType.qml

SomeType {
    ...
}

请注意,QML 模块内的文件会自动导入其所属的 QML 模块。您可以移除这些自导入。

另请参阅 《Qt Qml 的变更》和《QML 模块的现代化》。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.