How to Register your C++ Class as a QML Type :
The second possibility to use C++ components in QML is to register the class as a QML type. This allows to create objects (= instances)
of your type directly in QML instead of C++. And the best thing is, the
concepts with signals, slots and properties we used in the previous
example still apply.
When to Use a Context Property and when a QML Object
If there’s only a single object instance you want to work with in QML you can add the object as a context property
. When there can be multiple instances of your class, register it as a QML
type and create the objects directly in QML where you need it.
1. For this example, we will create a new type we can use in QML. Let’s start with adding a new C++ Class named SignalClass
.
2. Replace the code in signalclass.h
with this implementation:
#ifndef SIGNALCLASS_H
#define SIGNALCLASS_H
#include <QObject>
class SignalClass : public QObject
{
Q_OBJECT
public:
explicit SignalClass(QObject *parent = nullptr);
Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)
int count() const;
void setCount(int newCount);
public slots:
signals:
void countChanged();
private:
int m_count{0}; //initialize the value
};
#endif // SIGNALCLASS_H
3. To complete the class, add the following code for signalclass.cpp
:
#include "signalclass.h"
SignalClass::SignalClass(QObject *parent)
: QObject{parent}
{
}
int SignalClass::count() const
{
return m_count;
}
void SignalClass::setCount(int newCount)
{
if (m_count == newCount)
return;
m_count = newCount;
emit countChanged();
}
Register and Use your C++ QML Type
1. In your main.cpp, first add an include statement for the new class:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "signalclass.h"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
/*Register a class to available in QML*/
qmlRegisterType<SignalClass>("SignalMechnism",1,0,"SignalClass");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
The method takes several parameters: The module identifier and version define the required QML import to use the type. The last parameter holds the name of the QML type, which can be different from the actual C++ class name.
3. Add the import which matches the used configuration of qmlRegisterType to your main.qml:
import SignalMechnism 1.0
4. For an example usage of our new QML Type, add the following snippet below the first example in main.qml file:
SignalClass{
id:signalMech
}
Full main.qml file code
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.3
import SignalMechnism 1.0
ApplicationWindow {
width: 640
height: 480
visible: true
title: qsTr("Signal System Mechanism")
SignalClass{
id:signalMech
}
Label{
id:mylabel
text: qsTr("Current count is : ")+signalMech.count
font.pixelSize: 24
anchors.centerIn: parent
color: "Green"
}
Button{
text: qsTr("Count ++")
highlighted: true
anchors{
top: mylabel.bottom
topMargin: 20
horizontalCenter: parent.horizontalCenter
}
onClicked: {
signalMech.count = signalMech.count+1;
}
}
}
Note: You can find the whole source code on my github