В 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: