更详细的内容请参考 Qt 的官方文章:QML 中的单例

在 QML 项目中,配置散落各处是常见痛点。单例(Singleton)就是用来集中管理这些全局信息的最佳方案——每个 QML 引擎只创建一个实例,所有文件共享同一个对象。

一、两种推荐创建方式

1.1 纯 QML 单例

适合管理主题色、间距、API 地址等纯配置。

步骤

  1. 创建 QML 文件,首行加 pragma Singleton,根元素用 QtObject

    1
    2
    3
    4
    5
    6
    7
    8
    // Theme.qml
    pragma Singleton
    import QtQuick

    QtObject {
    property color primaryColor: "#3498db"
    property int spacing: 16
    }
  2. 在 CMake 中将文件标记为单例(须在 qt_add_qml_module 之前):

    1
    2
    set_source_files_properties(Theme.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
    qt_add_qml_module(myapp URI MyModule QML_FILES Theme.qml Main.qml)
  3. 使用时就导入模块,直接以文件名访问:

    1
    2
    3
    4
    5
    import MyModule

    Rectangle {
    color: Theme.primaryColor
    }

1.2 C++ 声明式单例

适合需要逻辑处理或 C++/QML 双端使用的场景。用宏声明即可:

1
2
3
4
5
6
7
8
9
class AppConfig : public QObject
{
Q_OBJECT
QML_SINGLETON
QML_ELEMENT
Q_PROPERTY(QString version READ version CONSTANT)
public:
QString version() const { return "1.0"; }
};

就这么简单,QML 中直接 import 对应模块,然后 AppConfig.version

二、为什么不推荐 Context Property

旧式的 setContextProperty() 查找慢、IDE 无法补全、编译器无法优化。单例有完整类型信息,是 Qt 6 的官方推荐。

三、几个关键点

  • 必须通过模块导入import Module),不能直接路径导入。
  • 根元素不能用可视类型(Item、Rectangle 等),必须用 QtObject
  • 每个 QML 引擎独立实例,如需跨引擎共享 C++ 实例,需要额外处理(本文略)。
  • 单例是延迟创建的,第一次访问时才实例化。

抛弃 context property,切换到单例,你的 QML 代码会更干净、更高效。