Ligar a lógica à sua interface de utilizador em QML
Para integrar a lógica na aplicação, iremos precisar das classes de infra-estrutura de C++ que conseguem fazer os cálculos importantes. O desenvolvimento de lógica nos ficheiros QML não é encorajado, pelo que deverá mover o máximo de código para a infra-estrutura, para que o QML seja praticamente usado apenas para a apresentação da interface de utilizador, que é onde ele é melhor.
Para a sua nova classe de infra-estrutura, crie dois ficheiros novos chamados backend.cpp
e backend.h
. Não se esqueça de adicionar o novo ficheiro .cpp ao executável no src/CMakeLists.txt
, junto ao main.cpp.
Adicione o seguinte conteúdo ao novo ficheiro de inclusão (backend.h
):
#pragma once
#include <QObject>
class Backend : public QObject
{
Q_OBJECT
public:
explicit Backend(QObject *parent = nullptr);
};
O ficheiro backend.cpp
que contém as definições está agora mais ou menos vazio, contendo algo como o seguinte:
#include "backend.h"
Backend::Backend(QObject *parent)
: QObject(parent)
{
}
De momento, a interface de utilizador não sabe nada sobre a sua classe de infra-estrutura. Para mudar isso, teremos de registar o novo tipo no main.cpp
. A infra-estrutura será criada como um singleton
, o que significa que só será criado uma vez e existirá durante todo o tempo, desde o início da aplicação até fechá-la.
Right after creating the QQmlApplicationEngine, add the type registration to main.cpp
as follows:
Backend backend;
qmlRegisterSingletonInstance<Backend>("org.kde.example", 1, 0, "Backend", &backend);
Não se esqueça de incluir o novo ficheiro de inclusão no topo do main.cpp
.
A partir de agora, a infra-estrutura ficará conhecida perante o QML como Backend
. Está contida dentro de um módulo chamado org.kde.example
. Dado que o módulo faz parte da aplicação, não precisa de se preocupar com a gestão de versões do mesmo; deixe-se ficar na 1.0
e use-a de forma consistente em toda a aplicação.
No main.qml
, importe o novo módulo:
import org.kde.example 1.0
Agora já ligámos a classe que trata da lógica futura com a aplicação, mas ainda não faz nada. Para mudar isso, vamos adicionar uma propriedade à classe. As propriedades são um pouco mais que uma simples variável. Elas conseguem informar a interface sobre alterações, pelo que poderá actualizar as áreas correctas.
Logo abaixo da macro Q_OBJECT, adicione uma nova Q_PROPERTY.
Q_PROPERTY(QString introductionText READ introductionText WRITE setIntroductionText NOTIFY introductionTextChanged)
Isto parece bastante para uma simples propriedade que iremos usar para mostrar algum texto da infra-estrutura. Mas uma vista mais aproximada revela que a mesma poderá executar lógica em código, quando a propriedade é lida a partir da interface do utilizador e quando é escrita. A mesma irá informar das alterações a nível da interface e da infra-estrutura.
A leitura e modificação são baseadas em funções 'getter' (leitura) e 'setter' (escrita); como tal, adicione um novo atributo privado à sua classe, como este, e adicione as funções de leitura e escrita mencionadas.
private:
QString m_introductionText = "Hello World!";
Na secção 'public', adicione
public:
QString introductionText() const;
void setIntroductionText(const QString &introductionText);
Q_SIGNAL void introductionTextChanged();
A primeira função é o método de leitura, a segunda é o método de escrita e a terceira é um sinal que é emitido quando a propriedade tiver sido modificada. O sinal não necessita de nenhuma implementação no ficheiro backend.cpp
, dado que não faz muito mais do que ser emitido, mas os métodos de leitura e escrita têm de ser implementados de forma semelhante à seguinte:
QString Backend::introductionText() const
{
return m_introductionText;
}
void Backend::setIntroductionText(const QString &introductionText)
{
m_introductionText = introductionText;
Q_EMIT introductionTextChanged();
}
Como poderá ver, quando for invocado o método de alteração, o sinal será emitido e informará a interface e a infra-estrutura da alteração.
Para mostrar o texto, no main.qml
adicione um cabeçalho que o mostra à direita da propriedade title
do elemento Kirigami.Page que já está contido dentro do modelo.
O código resultante dessa parte do ficheiro deverá ser semelhante ao seguinte:
// ...
Kirigami.Page {
title: i18n("develop.kde.org tutorial")
Kirigami.Heading {
anchors.centerIn: parent
text: Backend.introductionText
}
actions: [
Kirigami.Action {
// ...
}
]
}
Agora compile e inicie o seu programa de novo.
Parabéns, acabou de aprender:
- Como registar os tipos de infra-estruturas no QML
- Adicionar novos elementos ao ficheiros QML
- Criar novas sub-classes de QObject
- Como adicionar propriedades e o que fazem
- O que são os sinais ('signals')
If you want to know more about the integration between QML and C++, we recommend reading the official Qt documentation.