Berbagi teknologi

[catatan belajar qml] Interaksi antara QML dan C

2024-07-12

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

Interaksi antara QML dan C++

Akses objek c++ di QML
  • Pertama buat kelas. Kelas ini perlu diwarisi dari QObject dan harus dimilikiQ_OBJECTmakro, dan gabungQML_ELEMENTmakro, dan anggota swasta milikiQ_PROPERTYmakro (tersedia melaluiALT+ENTERPengaturan Cepat)
#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
  • Daftarkan objek dalam file cpp
//一定要通过创建对象来定义我们自定义的obj,对象存在于qml端
qmlRegisterType<MyCppObj>("MyCppObj.Obj",1,0,"MyCppObj");
//MyCppObj.Obj:import的库的名字
//1:主版本号
//0:次版本号
//MyCppObj:QML中类的名字
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • Impor ke file qml dan gunakan
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
Sinyal sisi QML terikat ke sisi C++ (terhubung di sisi qml)

Berdasarkan konten di atas, setelah menyelesaikan pendaftaran kelas c++

  • Deklarasikan fungsi slot:
public slots:
    void cppSlot(int i,QString s)
    {
    qDebug()<<__FUNCTION__<<i<<s;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • Menghubungkan di 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
  • Metode koneksi lain
Component.onCompleted:
    {
        qmlSignal.connect(myObj.cppSlot)
    }
  • 1
  • 2
  • 3
  • 4
Menghubungkan di sisi 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
Sinyal sisi C++ terikat ke sisi QML
  • Mengikat di sisi 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
  • Menghubungkan di sisi c++

Perhatikan bahwa parameter pihak pengirim dan penerima harus bertipe QVariant.

QObject::connect(myObj,SIGNAL(cppSignal(QVariant,QVariant)),window,SLOT(qmlSlot(QVariant,QVariant)));
  • 1
Daftarkan kelas tunggal

saat kita menggunakannyaqmlRegisterTypeKapan, kita perlu mendefinisikan objek khusus kita dengan membuat objek. Objek tersebut ada di sisi qml dan dapat digunakan ketika kita membutuhkan kelas untuk ada secara global.qmlRegisterSingletonInstance

 MyCppObj *myObj = new MyCppObj();
    qmlRegisterSingletonInstance("MyCppObjSingle",1,0,"MyCppObj",myObj);
  • 1
  • 2
Sisi C++ memanggil fungsi sisi QML
  • Dapatkan objek qml
auto list = engine.rootObjects();
    auto window = list.first();
  • 1
  • 2
  • Siapkan nilai dan parameter pengembalian
 QVariant res;
 QVariant arg_1 = 123;
 QVariant arg_2 = "ffffff";
  • 1
  • 2
  • 3
  • Dipanggil melalui 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