З'єднання логіки з вашим інтерфейсом користувача 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:
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
Щоб показати текст у main.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}}
Тепер зберіть і знову запустіть свою програму. Ви побачите, що нова сторінка має заголовок, розташований у центрі, з написом «Hello World!».
Вітаємо, ви навчилися:
Як реєструвати типи модулів обробки у QML
Додавати нові елементи до файла QML
Створювати підкласи QObject
Як додавати властивості і для чого вони потрібні
Що таке сигнали
Якщо ви хочете дізнатися про інтеграцію між QML і C++, ми рекомендуємо ознайомитися із офіційною документацією до Qt.