Q_INVOKABLE oder wie kann ich Qt Funktionen in Qml benutzen?
November 20, 2013 Hinterlasse einen Kommentar
Wir möchten in unserem Beispiel die Qt Funktion currentDateTime() in unserem Qml File benutzen um die aktuelle Zeit anzuzeigen.
Dazu fügen wir in unser myclass.h File die Beschreibung Q_INVOKABLE ein, was soviel heist wie die Funktion in Qml aufrufbar machen.
class MyClass : public QObject { Q_OBJECT public: MyClass(); ~MyClass(); Q_INVOKABLE QDateTime getCurrentDateTime() //<--- unser Name für die in qml Aufrufbare Funktion const { return QDateTime::currentDateTime(); //Eigentliche Qt-Funktion } signals: void setlabeltext(QString text); public slots: void cppSlot(QString msg); };
Jetzt müssen wir nur noch die Funktion irgendwie in unserem Qml file Aufrufen,
doch zuerst fügen wir in unser main.qml main_window über den Designer ein Rechteck und ein neues Label für Datum und Uhrzeit ein.
Diesen Label Text wollen wir nun jede Sekunde aktualisieren dazu verwenden wir die Vorher gelernte Möglichkeit C++ Signale mit Qml zu verbinden. (Den TextNamen text1 ändern wir noch auf datumzeit.)
Anschließend erstellen wir uns einen Timer und ein Signal sowie einen Slot in unserer myclass.h
#include <QObject> #include <QDateTime> #include <QDebug> #include <QTimer> class MyClass : public QObject { Q_OBJECT public: MyClass(); ~MyClass(); QTimer * SecondsTimer; Q_INVOKABLE QDateTime getCurrentDateTime() const { return QDateTime::currentDateTime(); } signals: void setlabeltext(QString text); void emit_timer_second(); public slots: void cppSlot(QString msg); void emit_timer(); };
Unsere main.cpp erweitern wir um den Slot emit_timer() und füllen den Konstruktor MyClass mit etwas Leben das einen Timer erzeugt,verbindet und startet.
#include <QtGui/QGuiApplication> #include "qtquick2applicationviewer.h" #include "myclass.h" #include <QQmlContext> #include <QDateTime> #include <QtCore> #include <QDebug> #include <QQuickItem> int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer; MyClass data; viewer.rootContext()->setContextProperty("myclassData", &data); viewer.setMainQmlFile(QStringLiteral("qml/qtquick_uebung/main.qml")); //Verbindung von C++ über Signal Slots nach QML QString msg = "Dieser Text kommt von c++"; emit data.setlabeltext(msg); //Verbindung von QML über Signal Slots nach C++ QObject* viewerobject = viewer.rootObject(); QObject::connect(viewerobject,SIGNAL(qmlSignal(QString)),&data,SLOT(cppSlot(QString))); MyClass(); //<-- hier wird myclass Aufgerufen viewer.showExpanded(); return app.exec(); } MyClass::MyClass() { SecondsTimer = new QTimer(this); QObject::connect(SecondsTimer,SIGNAL(timeout()),this,SLOT(emit_timer())); SecondsTimer->start(1000); } MyClass::~MyClass() { } void MyClass::cppSlot(QString msg) { qDebug() << QString("Called the C++ slot with message:%1").arg(msg); } void MyClass::emit_timer() { emit emit_timer_second(); }
Der Slot emit_timer() wird nun jede Sekunde aufgerufen und emittiert das Signal emit_timer_second(), dieses Signal fangen wir nun noch in Qml auf und setzen unsere Q_INVOKABLE Funktion ein um das DatumZeit Label auf die aktuelle Systemzeit zu setzen. Das Target für unser Signal ist immer noch myclassData daher fügen wir nun auch diesen Slot in Connections ein (Großbuchstabe beachten)
Connections { target: myclassData onSetlabeltext: { labeltext.text=text } onEmit_timer_second: { datumzeit.text=Qt.formatDateTime(myclassData.getCurrentDateTime(),"dd.MM.yyyy:hh.mm.ss") //<--datumzeit ist unser neues label das wir nun setzen } } Rectangle { //die neuen Elemente Hellgruenes Rechteck und Text datumzeit id: rectangle1 x: 0 y: 0 width: 360 height: 27 color: "#4dc635" Text { id: datumzeit x: 0 y: 0 width: 360 height: 27 text: Qt.formatDateTime(myclassData.getCurrentDateTime(),"dd.MM.yyyy:hh.mm.ss") //wenn wir von anfang an die aktuelle Zeit sehen wollen müssen wir den Text vorher setzen horizontalAlignment: Text.AlignRight font.pixelSize: 21 } }
und voila wir bekommen das aktuelle Datum und aktuelle Zeit in unserem Label angezeigt