Подключение логики к пользовательскому интерфейсу QML
Подключение бэкенда для выполнения вычислений и передачи данных в пользовательский интерфейс для показа
Чтобы внедрить логику в приложение, нужны классы бэкенда на C++, способные выполнять важные вычисления. Писать логику в файлах QML не рекомендуется, поэтому следует перенести как можно больше в бэкенд, чтобы QML использовался только для показа пользовательского интерфейса.
Сначала создайте заголовочный файл, в котором будет код, доступный для QML, а именно тип Backend:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma once
#include<QObject>#include<qqmlintegration.h>classBackend:publicQObject{Q_OBJECTQML_ELEMENTQML_SINGLETONpublic:explicitBackend(QObject*parent=nullptr);};
Чтобы сделать код C++ доступным для QML, нужно выполнить два действия, и одно из них — просто использовать макрос QML_ELEMENT, доступный в заголовочном файле <QtQml/qqmlregistration.h>.
Бэкенд будет создан как синглтон: он создаётся только один раз и существует в течение всего времени работы приложения. Для этого используется макрос QML_SINGLETON.
src/components/backend.cpp
Можно добавить начальный код конструктора в backend.cpp:
С этого момента QML будет знать бэкенд как тип QML Backend. Он содержится в модуле org.kde.tutorial.components.
Это означает, что достаточно добавить импорт в файл QML, чтобы использовать код, предоставляемый из C++:
importorg.kde.tutorial.components
Чтобы начать с чистого листа, используя существующий код приложения, создайте новый компонент QML, содержащий пустую страницу:
1
2
3
4
5
6
7
importorg.kde.kirigamiasKirigamiimportorg.kde.tutorial.componentsKirigami.Page{title:"Exposing to QML Tutorial"// ...
}
src/Main.qml
Чтобы новая страница действительно показывалась, создадим пункт меню, который помещает новую страницу в приложение, — просто чтобы модель было проще проверить.
globalDrawer:Kirigami.GlobalDrawer{isMenu:trueactions:[Kirigami.Action{text:i18n("Exposing to QML")icon.name:"kde"onTriggered:pageStack.push(Qt.createComponent("org.kde.tutorial.components","ExposePage"))},Kirigami.Action{text:i18n("Quit")icon.name:"application-exit-symbolic"shortcut:StandardKey.QuitonTriggered:Qt.quit()}]}
src/components/CMakeLists.txt
Наконец, добавьте только что созданные файлы backend.h, backend.cpp и ExposePage.qml в CMake:
Теперь класс, содержащий будущую логику, подключён к приложению, но он всё ещё ничего не делает. Чтобы это изменить, добавим в класс свойство. Свойства — это гораздо больше, чем простая переменная. Они могут сообщать пользовательскому интерфейсу об изменениях, чтобы он обновлял нужные области.
Непосредственно под макросом QML_SINGLETON добавьте новый макрос Q_PROPERTY.
Может показаться, что для простого чтения и записи кода из бэкенда требуется слишком много кода. Однако при более внимательном рассмотрении видно, что чтение свойства из пользовательского интерфейса уже может выполнять некоторую логику — то же самое при его записи. В этом случае свойство автоматически уведомит интерфейс и бэкенд об изменениях.
Чтение и запись основаны на концепции функций получения и установки. Добавьте в свой класс новый закрытый атрибут, хранящий данные, а также функции получения и установки для него.
Добавьте новый закрытый раздел со следующим кодом:
Первая функция — геттер (функция получения), вторая — сеттер (функция установки), а третья — сигнал, испускаемый при изменении свойства. Они соответствуют частям READ, WRITE и NOTIFY приведённого выше Q_PROPERTY.
В результате должно получиться следующее:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#pragma once
#include<QObject>#include<qqmlintegration.h>classBackend:publicQObject{Q_OBJECTQML_ELEMENTQML_SINGLETONQ_PROPERTY(QStringintroductionTextREADintroductionTextWRITEsetIntroductionTextNOTIFYintroductionTextChanged)public:explicitBackend(QObject*parent=nullptr);QStringintroductionText()const;voidsetIntroductionText(constQString&introductionText);Q_SIGNALvoidintroductionTextChanged();private:QStringm_introductionText=QStringLiteral("Hello World!");};
src/components/backend.cpp
Сигнал не требует реализации в файле backend.cpp, поскольку от него требуется лишь испускание, а функции получения и установки нужно реализовать так, как показано ниже:
Как видно, при вызове функции установки будет испущен сигнал, который уведомит пользовательский интерфейс и бэкенд об изменении.
src/components/ExposePage.qml
Чтобы показать текст, добавьте Kirigami.Heading в src/components/ExposePage.qml под свойством title компонента Kirigami.Page, добавленного в код.
В результате код в этой части файла должен выглядеть так:
1
2
3
4
5
6
7
8
9
10
importorg.kde.kirigamiasKirigamiimportorg.kde.tutorial.componentsKirigami.Page{title:"Exposing to QML Tutorial"Kirigami.Heading{anchors.centerIn:parenttext:Backend.introductionText}}
#pragma once
#include<QObject>#include<qqmlintegration.h>classBackend:publicQObject{Q_OBJECTQML_ELEMENTQML_SINGLETONQ_PROPERTY(QStringintroductionTextREADintroductionTextWRITEsetIntroductionTextNOTIFYintroductionTextChanged)public:explicitBackend(QObject*parent=nullptr);QStringintroductionText()const;voidsetIntroductionText(constQString&introductionText);Q_SIGNALvoidintroductionTextChanged();private:QStringm_introductionText=QStringLiteral("Hello World!");};
importorg.kde.kirigamiasKirigamiimportorg.kde.tutorial.componentsKirigami.Page{title:"Exposing to QML Tutorial"Kirigami.Heading{anchors.centerIn:parenttext:Backend.introductionText}}
Теперь соберите и снова запустите программу. На новой странице появится выровненный по центру заголовок Heading с текстом «Hello World!».