Technology Sharing

[QML learning notes] Interaction between QML and C

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Interaction between QML and C++

Accessing C++ objects in QML
  • First, create a class that inherits from QObject and must haveQ_OBJECTmacro, and addQML_ELEMENTmacro, and private members haveQ_PROPERTYMacros (available throughALT+ENTERQuick Setup)
#include <QObject>
#include <QtQml>//注意 QML_ELEMENT 需要该头文件
class MyCppObj : public QObject
{
    Q_OBJECT
    QML_ELEMENT
public:
    explicit MyCppObj(QObject *parent = nullptr);
    int iValue() const;
    void setIValue(int newIValue);
    
    QString string() const;
    void setString(const QString &newString);
    //加入 Q_INVOKABLE宏的函数才可在QML端进行访问
    Q_INVOKABLE void func();
    
private:
    int m_iValue;
    QString m_string;
    
    Q_PROPERTY(int iValue READ iValue WRITE setIValue NOTIFY iValueChanged FINAL)
    Q_PROPERTY(QString string READ string WRITE setString NOTIFY stringChanged FINAL)
    
signals:
    void iValueChanged();
    void stringChanged();
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • Register the object in the cpp file
//一定要通过创建对象来定义我们自定义的obj,对象存在于qml端
qmlRegisterType<MyCppObj>("MyCppObj.Obj",1,0,"MyCppObj");
//MyCppObj.Obj:import的库的名字
//1:主版本号
//0:次版本号
//MyCppObj:QML中类的名字
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • Import it in the qml file and use it
import QtQuick 2.15
import QtQuick.Window 2.15
import MyCppObj 1.0
Window {
    width: 640
    height: 480
    visible: true
    MyCppObj
    {
        id:myObj
        onIValueChanged: {}
        onSstringChanged: {}
    }
    Component.onCompleted:
    {
        console.log(myObj.iValue,myObj.sstring)
        myObj.func()
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
Bind QML signals to C++ signals (connect on qml side)

After completing the registration of the C++ class based on the above content

  • Declare the slot function:
public slots:
    void cppSlot(int i,QString s)
    {
    qDebug()<<__FUNCTION__<<i<<s;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • Connecting in QML
Window {
    id:window
    width: 640
    height: 480
    visible: true
    signal qmlSignal(int i,string s)
    MyCppObj
    {
        id:myObj
        onIValueChanged: {}
        onSstringChanged: {}
    }

    Button{
        onClicked:
        {
            qmlSignal(10,"666")
        }
    }
    Connections
    {
        target: window
        function onQmlSignal(i,s)
        {
            myObj.cppSlot(i,s);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • Another way to connect
Component.onCompleted:
    {
        qmlSignal.connect(myObj.cppSlot)
    }
  • 1
  • 2
  • 3
  • 4
Connecting on the C++ side
engine.load(url);
auto list = engine.rootObjects();//在engine.load之后
auto window = list.first();
MyCppObj *myObj = new MyCppObj();
    QObject::connect(window,SIGNAL(qmlSignal(int,QString)),myObj,SLOT(cppSlot(int,QString)));
  • 1
  • 2
  • 3
  • 4
  • 5
Binding C++ signals to QML
  • Binding on the qml side
 Button{
        onClicked:
        {
            myObj.cppSignal(10,"6")
        }
    }
    function qmlSlot(i,s)
    {
        console.log("qml",i,s)
    }
    Connections
    {
        target: myObj
        function onCppSignal(i,s)
        {
            qmlSlot(i,s);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • Connecting on the C++ side

Note that both the sender and receiver parameters should be of QVariant type

QObject::connect(myObj,SIGNAL(cppSignal(QVariant,QVariant)),window,SLOT(qmlSlot(QVariant,QVariant)));
  • 1
Registering a singleton class

When we useqmlRegisterTypeWhen we need to define our custom obj by creating an object, the object exists on the qml side. When we need the class to exist globally, we can useqmlRegisterSingletonInstance

 MyCppObj *myObj = new MyCppObj();
    qmlRegisterSingletonInstance("MyCppObjSingle",1,0,"MyCppObj",myObj);
  • 1
  • 2
C++ calls QML functions
  • Get qml object
auto list = engine.rootObjects();
    auto window = list.first();
  • 1
  • 2
  • Prepare return values ​​and parameters
 QVariant res;
 QVariant arg_1 = 123;
 QVariant arg_2 = "ffffff";
  • 1
  • 2
  • 3
  • Called via QMetaObject::invokeMethod
QMetaObject::invokeMethod(window,//获取到的qml对象
						 "qmlFunc",//需要调用的函数名
						  Q_RETURN_ARG(QVariant,res),//准备好的返回值和参数
						  Q_ARG(QVariant,arg_1),
						  Q_ARG(QVariant,arg_2));
  • 1
  • 2
  • 3
  • 4
  • 5