기술나눔

[qml 연구 노트] QML과 C 간의 상호 작용

2024-07-12

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

QML과 C++ 간의 상호 작용

QML에서 C++ 객체에 액세스
  • 먼저 클래스를 만듭니다. 이 클래스는 QObject에서 상속되어야 하며 다음을 가져야 합니다.Q_OBJECT매크로 및 조인QML_ELEMENT매크로 및 개인 멤버에는Q_PROPERTY매크로(다음을 통해 사용 가능ALT+ENTER빠른 설치)
#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
  • cpp 파일에 객체를 등록합니다.
//一定要通过创建对象来定义我们自定义的obj,对象存在于qml端
qmlRegisterType<MyCppObj>("MyCppObj.Obj",1,0,"MyCppObj");
//MyCppObj.Obj:import的库的名字
//1:主版本号
//0:次版本号
//MyCppObj:QML中类的名字
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • qml 파일로 import해서 사용하세요
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
QML 측 신호는 C++ 측에 바인딩됩니다(qml 측에 연결됨).

위 내용을 토대로 C++ 클래스 등록을 완료한 후

  • 슬롯 함수를 선언합니다.
public slots:
    void cppSlot(int i,QString s)
    {
    qDebug()<<__FUNCTION__<<i<<s;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 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
  • 또 다른 연결 방법
Component.onCompleted:
    {
        qmlSignal.connect(myObj.cppSlot)
    }
  • 1
  • 2
  • 3
  • 4
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
QML 측에 바인딩된 C++ 측 신호
  • 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
  • C++ 측에서 연결하기

송신측과 수신측 모두의 매개변수는 QVariant 유형이어야 합니다.

QObject::connect(myObj,SIGNAL(cppSignal(QVariant,QVariant)),window,SLOT(qmlSlot(QVariant,QVariant)));
  • 1
싱글톤 클래스 등록

우리가 사용할 때qmlRegisterType객체를 생성하여 사용자 정의 obj를 정의해야 하는 경우 객체는 qml 측에 존재하며 클래스가 전역적으로 존재해야 할 때 사용할 수 있습니다.qmlRegisterSingletonInstance

 MyCppObj *myObj = new MyCppObj();
    qmlRegisterSingletonInstance("MyCppObjSingle",1,0,"MyCppObj",myObj);
  • 1
  • 2
C++ 측에서는 QML 측 함수를 호출합니다.
  • qml 객체 가져오기
auto list = engine.rootObjects();
    auto window = list.first();
  • 1
  • 2
  • 반환 값 및 매개 변수 준비
 QVariant res;
 QVariant arg_1 = 123;
 QVariant arg_2 = "ffffff";
  • 1
  • 2
  • 3
  • 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