Partage de technologie

[notes d'étude qml] Interaction entre QML et C

2024-07-12

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

Interaction entre QML et C++

Accéder aux objets C++ dans QML
  • Créez d’abord une classe. Cette classe doit hériter de QObject et doit avoir.Q_OBJECTmacro et rejoignezQML_ELEMENTmacro, et les membres privés ontQ_PROPERTYmacro (disponible viaALT+ENTERInstallation rapide)
#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
  • Enregistrez l'objet dans le fichier cpp
//一定要通过创建对象来定义我们自定义的obj,对象存在于qml端
qmlRegisterType<MyCppObj>("MyCppObj.Obj",1,0,"MyCppObj");
//MyCppObj.Obj:import的库的名字
//1:主版本号
//0:次版本号
//MyCppObj:QML中类的名字
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • Importez-le dans le fichier qml et utilisez-le
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
Les signaux côté QML sont liés au côté C++ (connectés du côté qml)

Sur la base du contenu ci-dessus, après avoir terminé l'enregistrement de la classe c++

  • Déclarez la fonction slot :
public slots:
    void cppSlot(int i,QString s)
    {
    qDebug()<<__FUNCTION__<<i<<s;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • Connexion en 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
  • Une autre méthode de connexion
Component.onCompleted:
    {
        qmlSignal.connect(myObj.cppSlot)
    }
  • 1
  • 2
  • 3
  • 4
Connexion côté C++
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
Signaux côté C++ liés au côté QML
  • Liaison côté qml
 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
  • Connexion côté C++

Notez que les paramètres des parties émettrices et réceptrices doivent être de type QVariant.

QObject::connect(myObj,SIGNAL(cppSignal(QVariant,QVariant)),window,SLOT(qmlSlot(QVariant,QVariant)));
  • 1
Enregistrer une classe singleton

quand nous utilisonsqmlRegisterTypeQuand, nous devons définir notre obj personnalisé en créant un objet. L'objet existe du côté qml et peut être utilisé lorsque nous avons besoin que la classe existe globalement.qmlRegisterSingletonInstance

 MyCppObj *myObj = new MyCppObj();
    qmlRegisterSingletonInstance("MyCppObjSingle",1,0,"MyCppObj",myObj);
  • 1
  • 2
Le côté C++ appelle la fonction côté QML
  • Obtenir un objet QML
auto list = engine.rootObjects();
    auto window = list.first();
  • 1
  • 2
  • Préparer les valeurs de retour et les paramètres
 QVariant res;
 QVariant arg_1 = 123;
 QVariant arg_2 = "ffffff";
  • 1
  • 2
  • 3
  • Appelé 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