I have a QObject
derived class Expense
that I use in QML like this.
// main.qml
Expense {
id: expenseManager
onExpenseCreated: {
// Do something
}
}
The expense class has no UI components, it has some basic Signal and Slots for API communications.
// expense.h
#ifndef EXPENSE_H
#define EXPENSE_H
#include <QObject>
#include <QString>
#include "service.h"
class Expense : public QObject
{
Q_OBJECT
private:
Service service;
void networkError();
bool buttonLock = false;
public:
explicit Expense(QObject *parent = nullptr);
public slots:
void createInvoice(QString item, float amount);
signals:
void expenseCreated();
};
#endif // EXPENSE_H
I have used qmlRegisterType()
for registering Expense
type in QML. Below is how my main()
looks like.
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
......
qmlRegisterType<Expense>("com.kadbyte.expense", 1, 0, "Expense");
........
return app.exec();
}
Everything working perfectly as it used to. But recently I have upgraded my project to QT6 with CMake as the build tool instead of QMake. In the docs I saw that we can use qt_add_qml_module
command in CMakeList.txt to register C Classes instead of qmlRegisterType()
, by adding QML_ELEMENT
macro to the QObject class.
But I can't understand how to do this, the documentation doesn't make sense as it uses qmake example (Link to docs) instead of CMake. Below is my CMakeLists.txt file
cmake_minimum_required(VERSION 3.16)
project(Udyan VERSION 0.1 LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)
qt_add_executable(appUdyan
main.cpp
expense.h expense.cpp
)
qt_add_qml_module(appUdyan
URI Udyan
VERSION 1.0
QML_FILES qml/main.qml
)
set_target_properties(appUdyan PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
MACOSX_BUNDLE TRUE
WIN32_EXECUTABLE TRUE
)
target_compile_definitions(appUdyan
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(appUdyan
PRIVATE Qt6::Quick)
So how to use qt_add_qml_module
to registering QObject class to use in QML?
Note: All the example I have given above is just an MRE and not my complete code.
CodePudding user response:
You just need to add QML_ELEMENT
to your QObject-derived Expense
class's header and make sure you have moc enabled in your CMakeLists.txt. In application case it doesn't matter if the expense.h/cpp sources are included via qt_add_executable
or qt_add_qml_module
. I think it's clearer to add them to qt_add_qml_module
SOURCES. Then you just import module URI in you QML file. In the example below I'm printing out property value from Example object in QML.
CMakeLists.txt
set(CMAKE_AUTOMOC ON)
qt_add_qml_module(appUdyan
URI udyan
VERSION 1.0
QML_FILES
main.qml
SOURCES
expense.h
expense.cpp
)
C
#include <QObject>
#include <QtQml/qqmlregistration.h>
class Expense : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(int value READ value NOTIFY valueChanged)
public:
explicit Expense(QObject *parent = nullptr);
int value() const;
signals:
void valueChanged();
private:
int m_value {5};
};
QML:
import QtQuick
import udyan
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Expense {
id: expense
Component.onCompleted: console.log(expense.value)
}
}