В C++ для взаимодействия с кодом QML можно использовать сигналы, слоты и функции Q_INVOKABLE. Например, пусть в проекте определен класс Counter, код которого состоит из заголовочного файла counter.h и файла с реализацией counter.cpp:
В заголовочном файле counter.h определим следующий код:
#ifndef COUNTER_H
#define COUNTER_H
#include <QObject>
class Counter: public QObject
{
Q_OBJECT
public:
Counter(QObject *parent = nullptr){}
Q_INVOKABLE void decrease();
Q_INVOKABLE void increase();
signals:
void valueChanged(int);
private:
int value{};
};
#endif // COUNTER_H
Класс Counter наследуется от QObject и применяет макрос Q_OBJECT, благодаря чему класс может определять сигналы.
В классе определено приватное свойство value, в котором хранится некоторое значение объекта Counter. Также определено два метода - increase и decrease, которые будут изменять значение value. Благодаря макросу Q_INVOKABLE эти методы можно вызывать из кода QML.
И также определен сигнал valueChanged, который будет вызываться при изменении значения и через параметр которого будет передаваться новое значение.
В файле counter.cpp определим реализацию методов:
#include "counter.h"
void Counter::increase()
{
value++;
emit valueChanged(value);
}
void Counter::decrease()
{
value--;
emit valueChanged(value);
}
Методы увеличивают или уменьшают значение value на 1 и генерируют сигнал valueChanged, передавая в него обновленное значение.
В файле main.cpp зарегистрируем тип Counter:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "counter.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// регистрация типа Counter
qmlRegisterType<Counter>("counter", 1, 0,"Counter");
const QUrl url("qrc:/path/main.qml");
engine.load(url);
return app.exec();
}
Используем тип Counter в файле main.qml:
import QtQuick
import QtQuick.Controls
import counter
Window {
width: 250
height: 150
visible: true
title: "METANIT.COM"
function onValueChaged(newValue){
labelCount.text = newValue;
}
Counter{ id: counter}
Row{
spacing: 10
anchors.centerIn: parent
Button {
text: "+"
width: 25
height: 25
onClicked: counter.increase()
}
Text{
id: labelCount
}
Button {
text: "-"
width: 25
height: 25
onClicked: counter.decrease()
}
}
Component.onCompleted: {
counter.valueChanged.connect(onValueChaged)
}
}
Здесь определен элемент Counter с идентификатором counter, с которым будут взаимодействовать другие элементы. В частности, здесь также определены две кнопки, по нажатию на которые будут вызываться методы increase и decrease объекта counter.
При завершении загрузки компонента окна устанавливаем для сигнала valueChanged объекта Counter в качестве обработчика функцию onValueChaged:
counter.valueChanged.connect(onValueChaged)
В этой функции получаем новое значение объекта Counter и устанавливаем его в качестве текста элемента labelCount:
function onValueChaged(newValue){
labelCount.text = newValue;
}
Таким образом, при нажатии на кнопки произвойдет изменение значения в counter, и сработает событие valueChanged, которое будет обработано функцией onValueChaged: