[zero basic QT] [048] Qml and C + + call each other

In order to save code and focus on technology itself, we directly reuse main.qml from the previous blog to demonstrate

Qml code

	//main.qml
	
	import QtQuick 2.13
	import QtQuick.Window 2.13
	
	//Window node
	Window {
	    id: root
	    visible: true
	    width: 640
	    height: 480
	    title: "Qt Quick Demo"
	
	    IconButton {
	        anchors.fill: parent
	        anchors.margins: 100
	
	        icon: "images/1.png"
	        text: "Print Mouse Position"
	    }
	}

	//IconButton.qml

	IconButtonForm {
	    id: _root
	    width: 640
	    height: 480
	
	    //Click signal
	    signal clicked(var mouse)
	
	    //Click events
	    clickRect.onClicked: {
	        _root.clicked(mouse)
	    }
	    
	    //Monitor property change
	    onWidthChanged: {
	        console.debug("IconButton width change")
	    }

	    //Qml method
	    function sum(a, b) {
	        return a + b
	    }
	}
	

C + + loading Qml as an object
C + + can obtain the objects in Qml through QQmlComponent and QQuickView

	//QQmlComponent

	int main(int argc, char *argv[]) {
	    QGuiApplication app(argc, argv);
	
	    QQmlApplicationEngine engine;
	    QQmlComponent component(&engine, "qrc:///main.qml");  //Pay attention to the way of writing
	    QObject *object = component.create();
	    qdebug << object->metaObject()->className();  //The printing result is: QQuickWindowQmlImpl
	    QQuickWindow *window = qobject_cast<QQuickWindow *>(object);
	    qdebug << window->width();
	
	    return app.exec();
	}

	//QQuickView

	int main(int argc, char *argv[]) {
	    QGuiApplication app(argc, argv);
	
	    QQuickView view;  //QQuickView does not support Window as root node
	    view.setSource(QUrl("qrc:///IconButton.qml"));  //Pay attention to the way of writing
	    view.show();
	    QObject *object = view.rootObject();
	    qdebug << object->metaObject()->className();  //The result of printing is: iconbutton? Qmltype? 1
	    QQuickItem *item = qobject_cast<QQuickItem *>(object);
	    qdebug << item->width();
	
	    return app.exec();
	}

C + + controls the properties of Qml objects
There are two ways for C + + to control the properties of Qml objects: get/set and read/write
The difference between the two methods is that the latter will remove the constraints that existed before the attribute
For example, if we set [width:height] and call QQmlProperty::write(), the constraint will be released
The object properties read by C + + from Qml are all encapsulated by QVariant
When the object properties in Qml are changed through C + +, the property listener in Qml will be triggered. For example, when the width is changed, onWidthChanged will also execute

	int main(int argc, char *argv[]) {
	    QGuiApplication app(argc, argv);
	
	    QQuickView view;
	    view.setSource(QUrl("qrc:///IconButton.qml"));
	    view.show();
	    QObject *object = view.rootObject();
	
	    object->property("width");
	    object->setProperty("width", 1000);
	
	    QQmlProperty(object, "width").read();
	    QQmlProperty(object, "width").write(1000);
	
	    return app.exec();
	}

C + + calls Qml object methods

    QQuickView view;
    view.setSource(QUrl("qrc:///IconButton.qml"));
    view.show();
    QObject *object = view.rootObject();

    QVariant returnValue;
    QMetaObject::invokeMethod(object, "sum", Q_RETURN_ARG(QVariant, returnValue), Q_ARG(QVariant, 1), Q_ARG(QVariant, 2));
    qdebug << returnValue;

C + + slot function responds to Qml signal
The slot function in C + + and the signal in Qml can be connected according to the normal connect mode, because the parameters in the connect method are only strings in nature, and the rest of the work is done automatically by the Qt compiler. Since we already know the name of the signal and slot, we can write it directly
In order to define a C + + slot function, we need to add a QObject class. Because Qt requires that we must write the Q Ou object macro in the header file, we will change main.cpp to main.h, so that we can ensure that all codes are in the same file. Although it is not standard, it is convenient to explain

	//main.h
	
	class QmlClass : public QObject {
	    Q_OBJECT
	
	  public slots:
	    void onMouseClick(QVariant mouse) {
	        QObject *pEvent = mouse.value<QObject *>();
	        qdebug << pEvent->property("button");
	        qdebug << pEvent->property("y");
	        qdebug << pEvent->property("y");
	    }
	};
	
	int main(int argc, char *argv[]) {
	    QGuiApplication app(argc, argv);
	
	    QQuickView view;
	    view.setSource(QUrl("qrc:///IconButton.qml"));
	    view.show();
	    QObject *qmlObject = view.rootObject();
	
	    QmlClass qmlClass;
	    QObject::connect(qmlObject, SIGNAL(clicked(QVariant)), &qmlClass, SLOT(onMouseClick(QVariant)));
	
	    return app.exec();
	}


Qml uses classes in C + +

	//main.h

	#include <qlib.h>
	#include <QGuiApplication>
	#include <QQmlApplicationEngine>
	#include <QQuickView>
	
	class CppClass : public QObject {
	    Q_OBJECT
	
	    //Define a property that can be accessed in Qml
	    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
	
	  public:
	    QString name() {
	        return mName;
	    }
	
	    //When the name changes, it sends a signal, which can be responded in Qml
	    void setName(QString &name) {
	        if (name == mName) return;
	        QString temp = mName;
	        mName = name;
	        emit nameChanged(temp, name);
	    }
	
	    //Define a method that can be accessed in Qml
	    Q_INVOKABLE void printName() {
	        qdebug << name();
	    }
	
	  signals:
	    //Define the signal of name change, and the signal processor named onNameChanged will be generated automatically in Qml
	    void nameChanged(QString oldName, QString newName);
	
	  private:
	    QString mName;
	};
	
	int main(int argc, char *argv[]) {
	    QGuiApplication app(argc, argv);
	
		//Module name and class name registered in Qml
	    qmlRegisterType<CppClass>("cpp", 1, 0, "CppClass");
	
	    QQuickView view;
	    view.setSource(QUrl("qrc:///IconButton.qml"));
	    view.show();
	
	    return app.exec();
	}


	//IconButton.qml

	import QtQuick 2.13
	import cpp 1.0
	
	IconButtonForm {
	    id: _root
	    width: 640
	    height: 480
	
	    //Using classes in C + +
	    CppClass {
	        id: cppClass
	        name: "hello" //Using properties in C + +
	
	        //Respond to signals in C + +
	        onNameChanged: {
	            console.debug("onNameChanged:", oldName, newName)
	            printName() //Call methods in C + +
	        }
	    }
	
	    //Change the name of cppClass when clicking
	    clickRect.onClicked: {
	        cppClass.name = Math.random()
	    }
	}

417 original articles published, 43 praised, 120000 visitors+
His message board follow

Tags: Qt Attribute REST

Posted on Wed, 05 Feb 2020 05:32:37 -0800 by future448