Qt
Kommunikation mellan QML och C ++
Sök…
Introduktion
Vi kan använda QML för att bygga hybridapplikationer, eftersom det är mycket lättare än C ++. Så vi borde veta hur de kommunicerar med varandra.
Ring C ++ i QML
Registrera C ++ klasser i QML
På C ++ - sida, föreställ dig att vi har en klass som heter QmlCppBridge
, den implementerar en metod som heter printHello()
.
class QmlCppBridge : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE static void printHello() {
qDebug() << "Hello, QML!";
}
};
Vi vill använda det på QML-sida. Vi bör registrera klassen genom att ringa qmlRegisterType()
:
// Register C++ class as a QML module, 1 & 0 are the major and minor version of the QML module
qmlRegisterType<QmlCppBridge>("QmlCppBridge", 1, 0, "QmlCppBridge");
I QML använder du följande kod för att kalla det:
import QmlCppBridge 1.0 // Import this module, so we can use it in our QML script
QmlCppBridge {
id: bridge
}
bridge.printHello();
Med QQmlContext
att injicera C ++ klasser eller variabler till QML
Vi använder fortfarande C ++ -klassen i föregående exempel:
QQmlApplicationEngine engine;
QQmlContext *context = engine.rootContext();
// Inject C++ class to QML
context->setContextProperty(QStringLiteral("qmlCppBridge"), new QmlCppBridge(&engine));
// Inject C++ variable to QML
QString demoStr = QStringLiteral("demo");
context->setContextProperty(QStringLiteral("demoStr"), demoStr);
På QML-sida:
qmlCppBridge.printHello(); // Call to C++ function
str: demoStr // Fetch value of C++ variable
Obs: Detta exempel är baserat på Qt 5.7. Inte säker på om det passar tidigare Qt-versioner.
Ring QML i C ++
För att ringa QML-klasserna i C ++ måste du ange egenskapen objectName.
I din Qml:
import QtQuick.Controls 2.0
Button {
objectName: "buttonTest"
}
Sedan, i din C ++, kan du få objektet med QObject.FindChild<QObject*>(QString)
Sådär:
QQmlApplicationEngine engine;
QQmlComponent component(&engine, QUrl(QLatin1String("qrc:/main.qml")));
QObject *mainPage = component.create();
QObject* item = mainPage->findChild<QObject *>("buttonTest");
Nu har du ditt QML-objekt i ditt C ++. Men det kan verka värdelöst eftersom vi inte riktigt kan få objektets komponenter.
Vi kan dock använda den för att skicka signaler mellan QML och C ++. För att göra det måste du lägga till en signal i din QML-fil så: signal buttonClicked(string str)
. När du skapar detta måste du avge signalen. Till exempel:
import QtQuick 2.0
import QtQuick.Controls 2.1
Button {
id: buttonTest
objectName: "buttonTest"
signal clickedButton(string str)
onClicked: {
buttonTest.clickedButton("clicked !")
}
}
Här har vi vår qml-knapp. När vi klickar på den går den till onClicked- metoden (en basmetod för knappar som kallas när du trycker på knappen). Sedan använder vi knappen på knappen och namnet på signalen för att avge signalen.
Och i vår cpp måste vi ansluta signalen till en lucka. sådär:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include "ButtonManager.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QQmlComponent component(&engine, QUrl(QLatin1String("qrc:/main.qml")));
QObject *mainPage = component.create();
QObject* item = mainPage->findChild<QObject *>("buttonTest");
ButtonManager buttonManager(mainPage);
QObject::connect(item, SIGNAL(clickedButton(QString)), &buttonManager, SLOT(onButtonClicked(QString)));
return app.exec();
}
Som ni ser får vi vår qml-knapp med findChild
som tidigare och vi kopplar signalen till en knapphanterare som är en klass skapad och som ser ut så. ButtonManager.h
#ifndef BUTTONMANAGER_H
#define BUTTONMANAGER_H
#include <QObject>
class ButtonManager : public QObject
{
Q_OBJECT
public:
ButtonManager(QObject* parent = nullptr);
public slots:
void onButtonClicked(QString str);
};
#endif // BUTTONMANAGER_H
ButtonManager.cpp
#include "ButtonManager.h"
#include <QDebug>
ButtonManager::ButtonManager(QObject *parent)
: QObject(parent)
{
}
void ButtonManager::onButtonClicked(QString str)
{
qDebug() << "button: " << str;
}
Så när signalen kommer att mottas kommer den att ringa metoden onButtonClicked
som kommer att skriva "button: clicked !"
produktion: