Conectar un motor para realizar cálculos y suministrar los datos a mostrar en la interfaz de usuario
To integrate logic into the application, we need C++ backend classes that can do the important calculations. Writing logic in the QML files is discouraged, so try to move as much as possible to the backend such that QML is used only for displaying the user interface.
Primero, creamos el archivo de cabecera que tendrá el código expuesto a QML, es decir, el tipo 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);};
Hay dos cosas que necesitan exponer código C++ a QML, y una de ellas solo es el uso de la macro QML_ELEMENT, disponible en la cabecera <QtQml/qqmlregistration.h>.
El backend se creará como un singleton, lo que significa que solo se creará una vez y existirá durante toda la vida útil de la aplicación. Para ello, usamos la macro QML_SINGLETON.
src/components/backend.cpp
Podemos añadir nuestro código inicial para el constructor en 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
Lastly, add the newly created backend.h, backend.cpp and ExposePage.qml to CMake:
Ahora hemos conectado la clase que contiene la futura lógica a la aplicación, pero todavía no hace nada. Para cambiar esto, vamos a añadir una propiedad a la clase. Las propiedades son mucho más que una simple variable. Pueden informar a la interfaz de usuario de los cambios para que pueda actualizar las áreas correctas.
Right under the QML_SINGLETON macro, add a new Q_PROPERTY.
Esto puede parecer una gran cantidad de código para solo leer y escribir código desde el motor. Sin embargo, una mirada más cercana revela que leer la propiedad de la interfaz de usuario ya puede ejecutar cierta lógica (lo mismo ocurre cuando se escribe en ella). En este caso, informará automáticamente a la interfaz y al motor de los cambios.
La lectura y la escritura están basadas en los conceptos de las funciones getter y setter. Siga adelante y añada un nuevo atributo privado a la clase para contener los datos, así como las pertinentes funciones getter y setter.
The first function is the getter, the second the setter, and the third a signal that is emitted when the property is changed. They match the READ, WRITE and NOTIFY parts of the above Q_PROPERTY.
The result should look like the following:
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
The signal doesn't need any implementation in the backend.cpp file, since it doesn't do much more than being emitted, but the getter and setter need to be implemented similar to the following:
Como puede ver, cuando se llama al setter, se emite la señal y se informa a la interfaz de usuario y al motor del cambio.
src/components/ExposePage.qml
To display the text, add a Kirigami.Heading to src/components/ExposePage.qml under the title property of the Kirigami.Page component we added to the code.
El código resultante en esta parte del archivo debería parecerse a esto:
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}}
Now compile and start your program again. You'll see that the new page has a centered Heading saying "Hello World!".
¡Enhorabuena! Ha aprendido lo siguiente:
Cómo registrar tipos de motores en QML
Añadir nuevos elementos al archivo QML
Crear nuevas subclases de QObject
Cómo añadir propiedades y lo que hacen
Qué son las señales
Si quiere saber más sobre la integración entre QML y C++, le recomendamos que lea la documentación oficial de Qt.