Registering C++ Classes in QML Using Qt6 Macros

In Qt6, the qt_add_qml_module CMake API integrates with C++ classes through specific macros to streamline the type registration process.

  • QML_ELEMENT: Automatical registers the C++ class with the QML type system. This eliminates the need for manual registration calls like qmlRegisterType.
  • QML_SINGLETON: Declares the class as a singleton. This ensures that all QML components share a single instance of the class. Without this macro, a new object is instantiated every time the type is referenced in QML.
  • Q_GLOBAL_STATIC: A Qt macro used to create thread-safe, lazily initialized global static objects.

Standard Type Registration (Non-Singleton)

By default, a class marked with QML_ELEMENT behaves as a standard QML type. Each usage in QML creates a distinct instance.

1. C++ Class Definition

Define a class MessageHandler that inherits from QObject. Use the QML_ELEMENT macro to expose it to QML.

// messagehandler.h
#pragma once

#include <QObject>
#include <QtQml/qqml.h>

class MessageHandler : public QObject
{
    Q_OBJECT
    QML_ELEMENT

public:
    explicit MessageHandler(QObject *parent = nullptr);

    Q_INVOKABLE QString fetchStatus();
};

// messagehandler.cpp
#include "messagehandler.h"

MessageHandler::MessageHandler(QObject *parent) : QObject(parent) {}

QString MessageHandler::fetchStatus() {
    return "System Initialized";
}

2. CMake Configuration

Add the class to the QML module definition in your CMakeLists.txt file.

qt_add_qml_module(your_application_target
    URI CoreModule
    VERSION 1.0
    SOURCES
        messagehandler.cpp messagehandler.h
)

3. QML Usage

Instantiate the component in QML to create a new object.

// main.qml
import QtQuick 2.15
import CoreModule 1.0

Item {
    width: 400
    height: 300

    MessageHandler {
        id: commHandler
    }

    Text {
        anchors.centerIn: parent
        text: commHandler.fetchStatus()
    }
}

Singleton Pattern Implementation

Singletons ensure a single shared instance. There are two strategies for managing the instance lifecycle: sharing across all QML engines or scoping to a specific engine.

Shared Instance Across Engines

To share a single instance globally (even across multiple QML engines), you must implement a static factory functon with the signature create(QQmlEngine*, QJSEngine*). Use Q_GLOBAL_STATIC to manage the instance manually.

// appconfig.h
#pragma once

#include <QObject>
#include <QQmlEngine>
#include <QtQml>

class AppConfig : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_SINGLETON

public:
    explicit AppConfig(QObject *parent = nullptr);

    // Factory method required for shared singletons
    static AppConfig *create(QQmlEngine *engine, QJSEngine *scriptEngine);

    Q_INVOKABLE QString getApiKey();

private:
    static QString m_apiKey;
};

// appconfig.cpp
#include "appconfig.h"

Q_GLOBAL_STATIC(AppConfig, globalAppConfig)

AppConfig::AppConfig(QObject *parent) : QObject(parent) {}

// Returns the shared instance managed by Q_GLOBAL_STATIC
AppConfig *AppConfig::create(QQmlEngine *engine, QJSEngine *scriptEngine)
{
    Q_UNUSED(engine)
    Q_UNUSED(scriptEngine)
    return globalAppConfig();
}

QString AppConfig::getApiKey() {
    return "SHARED_KEY_123";
}

In QML, access the singleton directly using the type name without creating an object.

// main.qml
import QtQuick 2.15
import CoreModule 1.0

Item {
    Text {
        text: AppConfig.getApiKey() // Direct access
    }
}

Per-Engine Singleton

If the static factory method is omitted, the QML angine assumes responsibility for the singleton's lifecycle. It will construct one instance per engine using the default constructor.

// engineconfig.h
class EngineConfig : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    QML_SINGLETON

public:
    explicit EngineConfig(QObject *parent = nullptr);
    Q_INVOKABLE QString getSetting();
};

This approach provides a singleton within the scope of a specific QML engine but does not share the instance globally across different engine instances.

Tags: Qt6 QML C++ QML_ELEMENT QML_SINGLETON

Posted on Thu, 10 Sep 2026 16:35:46 +0000 by Tazerenix