将 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 target,你可以用它来确定潜在的问题或改进。例如,对于名为MyQmlLibrary 的 QML 模块,请使用MyQmlLibrary_qmllint 。要在所有 QML 模块上运行qmllint,请使用all_qmllint

qmllint提示 QML 模块问题的警告类别有

为 qt_add_qml_module 准备项目

在 CMake 中使 qt_add_qml_module 可用

要使qt_add_qml_module在 CMake 中可用,请在项目的顶级CMakeLists.txt 文件中的find_package 调用中添加CoreQml

find_package(Qt6 REQUIRED COMPONENTS Core Qml)

使用 qt_standard_project_setup

qt_standard_project_setup设置qt_add_qml_module 所需的Qt CMake 策略

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

qt_standard_project_setup(REQUIRES 6.8)

使用 qt_add_qml_module

qt_add_qml_module是负责生成 QML 模块的 CMake 函数。它会自动生成qmldirqmltypes 文件,并设置qmlcachegenqmllint 等工具。

QML 模块可以添加到 CMake 的可执行目标和库目标中。附加到可执行目标的 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::loadFromModuleQQmlComponent::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 target 还不存在,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 中有 singletons,请在调用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_moduleRESOURCES 参数中。您可以在:/qt/qml/MyQmlLibraryModule/ 下找到模块的资源。

用 QML 模块导入替换目录导入

用 QML 模块导入替换目录导入。例如

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

SomeType {
    ...
}

注意 QML 模块内的文件会自动导入它们自己的 QML 模块。您可以移除自导入。

另请参阅 Qt QMLModern QML 模块的更改

© 2025 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.