Conectar la lógica a la interfaz de usuario QML

Conectar un motor para realizar cálculos y suministrar los datos a mostrar en la interfaz de usuario

Para integrar la lógica en la aplicación, necesitamos clases de motores C++ que puedan realizar los cálculos importantes. No se aconseja escribir la lógica en los archivos QML, por lo que debería intentar mover todo lo que le sea posible al motor, de modo que QML se use exclusivamente para mostrar la interfaz de usuario, que es lo que hace mejor.

Para la nueva clase de motor, cree dos archivos llamados backend.cpp y backend.h. No se olvide de añadir el nuevo archivo cpp al ejecutable en src/CMakeLists.txt, junto a main.cpp.

Añada el siguiente contenido al nuevo archivo de cabecera (el que tiene la extensión .h):

#pragma once

#include <QObject>

class Backend : public QObject
{
    Q_OBJECT

public:
    explicit Backend(QObject *parent = nullptr);
};

El archivo cpp que contiene las definiciones también está vacío ahora; debe contener algo similar a lo siguiente:

#include "backend.h"

Backend::Backend(QObject *parent)
    : QObject(parent)
{

}

Hasta ahora, la interfaz de usuario no sabe nada sobre la clase del motor. Para cambiar esto, necesitamos registrar el nuevo tipo en main.cpp. El motor se creará como singleton, lo que significa que solo se creará una vez y existirá durante todo el tiempo, desde que se inicia la aplicación hasta que se cierra.

Para main.cpp, justo después de crear el QQmlApplicationEngine, añada el registro del tipo como sigue:

    Backend backend;
    qmlRegisterSingletonInstance<Backend>("org.kde.example", 1, 0, "Backend", &backend);

No olvide incluir el nuevo archivo de cabecera al principio de main.cpp.

A partir de este momento, QML conocerá el motor como Backend. Está contenido en un módulo llamado org.kde.example. Como el módulo es parte de la aplicación, no tiene que preocuparse por su número de versión: solo tiene que quedarse con 1.0 y usarlo de forma consistente en toda la aplicación.

En main.qml, importe el nuevo módulo:

import org.kde.example 1.0

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.

Justo debajo de la macro Q_OBJECT, añada una nueva Q_PROPERTY.

Q_PROPERTY(QString introductionText READ introductionText WRITE setIntroductionText NOTIFY introductionTextChanged)

Esto parece demasiado para una simple propiedad que vamos a usar para mostrar algo de texto desde el motor, ¿verdad? Pero una mirada más cercana revela que esto ya puede ejecutar la lógica cuando la interfaz de usuario lee la propiedad y cuando se escribe un valor en ella. Informará automáticamente a la interfaz y al motor de los cambios.

La lectura y la escritura están basadas en las funciones getter y setter, por lo que debe añadir un nuevo atributo private a su clase, como este, y añadir las funciones getter y setter.

private:
    QString m_introductionText = "Hello World!";

En la sección public, añada

    QString introductionText() const;
    void setIntroductionText(const QString &introductionText);
    Q_SIGNAL void introductionTextChanged();

La primera función es el gette, la segunda es el setter y la tercera es una señal que se emite cada vez que se cambie la propiedad. La señal no necesita estar implementada en el archivo cpp, ya que no hace otra cosa que emitirse, aunque el getter y el setter deben implementarse de un modo similar al siguiente:

QString Backend::introductionText() const
{
    return m_introductionText;
}

void Backend::setIntroductionText(const QString &introductionText)
{
    m_introductionText = introductionText;
    Q_EMIT introductionTextChanged();
}

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.

Para mostrar el texto, añada un encabezado para mostrarlo en main.qml justo debajo de la propiedad de texto del elemento Kirigami.Page que ya contiene la plantilla.

El código resultante en esta parte del archivo debería parecerse a esto:

        ...
        Kirigami.Page {
            title: i18n("develop.kde.org tutorial")

            Kirigami.Heading {
                anchors.centerIn: parent
                text: Backend.introductionText
            }

            actions {
                main: Kirigami.Action {
                    ...

Ahora, vuelva a compilar el programa y ejecútelo.

¡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.