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 (backend.h):

#pragma once

#include <QObject>

class Backend : public QObject
{
    Q_OBJECT

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

El archivo backend.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.

Después de crear el QQmlApplicationEngine , añada el registro de tipo a main.cpp de este modo:

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

private:
    QString m_introductionText = "Hello World!";

En la sección public, añada

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

La primera función es el getter, 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 backend.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 a main.qml bajo la propiedad title 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.