Conectar funcionalidad C++ con la interfaz QML Desde QML puede acceder a cada "propiedad" definida en su funcionalidad ó código C++. El código QML final de acceso quedará:
Copy Backend.introductionText
Otra forma de nombrar funcionalidad en otro ejemplo distinto podría ser:
1. Añade el siguiente código a un nuevo archivo (KDevelop > File > New) y guardalo en tu aplicación MauiKit en myapp/src/code/backend.h:
Copy #pragma once
#include <QObject>
#include <QDebug>
class Backend : public QObject
{
Q_OBJECT
Q_PROPERTY(QString introductionText READ introductionText WRITE setIntroductionText NOTIFY introductionTextChanged)
public:
explicit Backend(QObject *parent = nullptr);
public:
QString introductionText() const;
void setIntroductionText(const QString &introductionText);
Q_SIGNAL void introductionTextChanged();
private:
QString m_introductionText;
private slots:
void on_IntroductionTextChanged();
};
2. Añade la implementación a un nuevo archivo en myapp/src/code/backend.cpp:
Copy #include "backend.h"
Backend::Backend(QObject *parent)
: QObject(parent)
{
connect(this, SIGNAL(introductionTextChanged()), this, SLOT(on_IntroductionTextChanged()));
m_introductionText = "Hello World!";
}
QString Backend::introductionText() const
{
return m_introductionText;
}
void Backend::setIntroductionText(const QString &introductionText)
{
m_introductionText = introductionText;
Q_EMIT introductionTextChanged();
}
void Backend::on_IntroductionTextChanged()
{
qDebug() << "entra en slot";
}
3. Añade en main.cpp:
#include "backend.h"
4. Añade en main.cpp, justo después de la línea "QQmlApplicationEngine engine;":
Copy Backend backend;
qmlRegisterSingletonInstance<Backend>("org.kde.myapp", 1, 0, "Backend", &backend);
5. Añade en myapp/src/CMakeLists.txt:
Copy set(project_SRCS
code/main.cpp
assets/assets.qrc
code/backend.cpp
)
No se confunda con myapp/CMakeLists.txt
El archivo correcto es myapp/src/CMakeLists.txt
6. Añada en el fichero qml en el que quiera acceder a la funcionalidad C++ el siguiente código.
Para establecer la conexión entre la funcionalidad C++ y la interfaz QML:
Copy import org.kde.myapp 1.0
Para leer y escribir:
Copy text: Backend.introductionText
Backend.introductionText = "Be happy"
En el siguiente ejemplo se añade a main.qml:
Copy import QtQuick 2.15
import QtQuick.Controls 2.15
import org.mauikit.controls 1.3 as Maui
import org.kde.myapp 1.0
Maui.ApplicationWindow
{
id: root
Maui.Page {
id: page
anchors.fill: parent
showCSDControls: true
headBar.leftContent: ToolButton {
icon.name: "typewriter"
flat: true
onClicked: {
Backend.introductionText = "Be happy"
}
}
Label {
anchors.centerIn: parent
text: Backend.introductionText
}
}
}
Pasar múltiples datos en una sola propiedad desde código C++ a la interfaz QML: QVariantList.
En el siguiente ejemplo se crea la propiedad "users" conteniendo "name", "surname", "active" y "age". La propiedad "users" será leída y escrita desde QML.
1. Sustituya el paso 1 y añada a myapp/src/code/backend.h
Copy #pragma once
#include <QObject>
#include <QDebug>
#include <QVariantList>
class Backend : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariantList users READ users WRITE setUsers NOTIFY usersChanged)
public:
explicit Backend(QObject *parent = nullptr);
public:
QVariantList users() const;
void setUsers(const QVariantList &users);
Q_SIGNAL void usersChanged();
private:
QVariantList m_users;
private slots:
void on_UsersChanged();
};
2. Sustituya el paso 2 y añada a myapp/src/code/backend.cpp
Copy #include "backend.h"
#include <QVariantMap>
Backend::Backend(QObject *parent)
: QObject(parent)
{
connect(this, SIGNAL(usersChanged()), this, SLOT(on_UsersChanged()));
QVariantMap user1;
user1["name"] = "John";
user1["subname"] = "Candy";
user1["active"] = "false";
user1["age"] = 43;
QVariantMap user2;
user2["name"] = "Errol";
user2["subname"] = "Flynn";
user2["active"] = "false";
user2["age"] = 50;
m_users.append(user1);
m_users.append(user2);
}
QVariantList Backend::users() const
{
return m_users;
}
void Backend::setUsers(const QVariantList &users)
{
m_users = users;
Q_EMIT usersChanged();
}
void Backend::on_UsersChanged()
{
qDebug() << "entra en slot: user changed";
}
En una programación más realista sería parecido a esto:
Copy for (int i = 0; i < max; i++) {
QVariantMap user;
user["name"] = data1[i];
user["active"] = data2[i];
m_users.append(user);
}
3. Sustituya el paso 6 y añada a main.qml:
Copy import QtQuick 2.15
import QtQuick.Controls 2.15
import org.mauikit.controls 1.3 as Maui
import org.kde.myapp 1.0
Maui.ApplicationWindow
{
id: root
Maui.Page {
id: page
anchors.fill: parent
showCSDControls: true
headBar.leftContent: ToolButton {
icon.name: "typewriter"
flat: true
onClicked: {
var users = Backend.users
users[0].name = "Johnny"
Backend.users = users
}
}
Label {
id: label
anchors.centerIn: parent
text: Backend.users[0].name
}
}
}
Para leer desde C++ el objeto QVariantList "users" y acceder a la información de cada usuario puede usar el siguiente código donde desee. En este caso en la función de respuesta a usuario cambiado:
Copy void Backend::on_UsersChanged()
{
qDebug() << "entra en slot: user changed";
QVariantMap user = m_users[0].toMap();
QString name = user["name"].toString();
qDebug() << name;
}
La salida de consola de KDevelop muestra (iniciar ejecución pulsando click sobre botón Debug):
Copy entra en slot: user changed
"Johnny"
Invocar funciones C++ desde QML.
La macro Q_INVOKABLE permite invocar una función C++ desde código de interfaz QML.
1. Añade en myapp/src/code/backend.h:
Copy public:
Q_INVOKABLE void setOption(QString option);
2. Añade en myapp/src/code/backend.cpp:
Copy void Backend::setOption(QString option)
{
qDebug() << option;
}
3. Añade en main.qml:
Copy headBar.leftContent: ToolButton {
icon.name: "configure"
flat: true
onClicked: {
Backend.setOption("option 1")
}
}
Last updated 10 months ago