【Qt- C++ Qml 交互】

Qt编程指南 VX:hao541022348

  • ■ 将C++对象注册到 QML中,在QML使用C++对象(Q_INVOKABLE宏)
    • ■ C++对象注册到元对象系统
    • ■ Q_INVOKABLE 宏
    • ■ 演示步骤
  • ■ 将C++对象注册到 QML中,在QML使用C++对象(Q_PROPERTY宏 属性绑定)
    • ■ C++对象注册到元对象系统
    • ■ Q_PROPERTY 宏
    • ■ 演示代码
  • ■ 将 C++类注册到 QML,并在QML声明一个对象并进行访问
    • ■ C++类注册到qml中
    • ■ 演示代码
  • ■ 将 C++类注册到 QML,信号与槽进行交互
    • ■ C++类注册到qml中
    • ■ 演示代码
  • ■ 将C++中的数据模型注册到C++中,qml进行访问 --- 模型视图
    • ■ C++数据模型对象注册到元对象系统
    • ■ 演示代码
  • ■ C++使用QML
    • ■ 代码演示

■ 将C++对象注册到 QML中,在QML使用C++对象(Q_INVOKABLE宏)

在 C++ 里定义了一个对象,然后将这个对象注册到 QML 里面。在 QML 里面访问的就是 C++ 定义的对象。

■ C++对象注册到元对象系统

QQmlApplicationEngine::rootContext()->setContextProperty()

■ Q_INVOKABLE 宏

Q_INVOKABLE
Q_INVOKABLE 是个宏定义,这个宏将 函数 声明为元对象系统可调用的函数

  • Q_INVOKABLE 是个宏定义
  • 这个宏定义 针对的是 函数, 不是变量
  • 经过Q_INVOKABLE 声明过得函数 可以被元对象系统调用
  • QtQuick 也在元对象系统内,所以在 QML 中也可以访问这个被声明了的函数

■ 演示步骤

  1. 新建qml工程,里面只有一个main.cpp 与一个默认的 main.qml
  2. 创建一个C++ 的类 MyQmlClass 来与 QML 进行交互(重点关注 函数 Q_INVOKABLE宏
  3. 将 C++ 的对象,注册到 QML中去 QQmlApplicationEngine::rootContext()->setContextProperty()
  4. 做完了这两步,我们就做了 C++ 的工作,在 QML 中 就可以 直接拿到对象 myQmlImp 来调用使用 Q_INVOKABLE 定义的方法了。
  5. 改造 QML (定义一个“获取”的 Button 与 显示获取值得 Label, 点击 Button 就会获取 C++ 中的 m_value 值, 在 Lable 上进行展示。)

MyQmlClass.h

#ifndef MYQMLCLASS_H
#define MYQMLCLASS_H
 
#include <QObject> 
class MyQmlClass : public QObject
{
    Q_OBJECT
public:
    explicit MyQmlClass(QObject *parent = nullptr);
 
    Q_INVOKABLE void setValue(int value);    //这个宏将 函数 声明为元对象系统可调用的函数
    Q_INVOKABLE int getValue();   //这个宏将 函数 声明为元对象系统可调用的函数
 
signals:
 
private:
    int m_Value;
};
 
#endif // MYQMLCLASS_H

MyQmlClass.cpp

#include "MyQmlClass.h"
 
MyQmlClass::MyQmlClass(QObject *parent) : QObject(parent)
{
 
}
 
void MyQmlClass::setValue(int value)
{
    m_Value = value;
}
 
int MyQmlClass::getValue()
{
    return m_Value;
}

打开 main.cpp ,通过 QML 引擎 QQmlApplicationEngine 进行注册。

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
 
#include "MyQmlClass.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 
    QGuiApplication app(argc, argv); 
    QQmlApplicationEngine engine;
 
    ///
    //声明 对象  首先定义了一个C++ 的对象 myQmlImp ,
    MyQmlClass myQmlImp; 
    //将对象进行注册到QML中
    //key :自定义字符串,为了好记,我们这里叫做对象的名字 "myQmlImp"
	//value : 对象引用,对象指针,这里就是&myQmlImp
    engine.rootContext()->setContextProperty("myQmlImp", &myQmlImp);
 
    /// 
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
 
    return app.exec();
}

main.qml我们的思路很简单,就是 QML 中来调用上面 C++ 暴露出来的读写函数。所以我们在QML 中定义一个 “获取” Button ,点击它我们就来调用C++中的 getValue() 函数,然后我们需要一个Label 将获取的 C++ 的值进行展示

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.3
 
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
 
    Label{                         //Label用于显示获取C++的值
        id: label                  //显示控件,唯一标识ID:label
        text: ""                   //初始化内容清空
 
        anchors.bottom: getBtn.top //显示控件的下方放到btn的上方
        anchors.left: getBtn.left  //显示控件的左方与btn的左侧对齐
    }
 
    Button{                       //Button 用于获取值
        id: getBtn                 //按钮控件,唯一标识ID:getBtn
        text: "获取"                //按钮显示文字
        width: 120                 //按钮宽度
        height: 40                 //按钮高度
 
        anchors.centerIn: parent   //按钮放到窗口中心
 
        onClicked: {               //点击按钮事件;
            label.text = myQmlImp.getValue()
        }
    }
}

在这里插入图片描述
到这里,我们就在 QML 中获取了 C++ 代码中的值。可能到这里还有老师感觉不太真实,那么我们就继续进行验证,我们的思路是这样的:

  1. 我们增加一个 TextFiled 用于输入我们想给 。
  2. 再增加一个 “设置” 按钮,将 1中输入的值,给C++ 中的 m_Value 设值。
  3. 然后我们再点击刚才的 “获取” 按钮,将 C++ 中的 m_Value 值读取并显示出来。
    这时候我们需要对原来的QML进行改造,新增加一个输入框TextField ,进行数值输入; 还需要新增加一个“设置” 按钮,点击按钮将值赋给 C++ 中的 m_Value

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.3
 
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World") 
 
    Label{                         //Label用于显示获取C++的值
        id: label                  //显示控件,唯一标识ID:label
        text: ""                   //初始化内容清空
 
        anchors.bottom: getBtn.top //显示控件的下方放到btn的上方
        anchors.left: getBtn.left  //显示控件的左方与btn的左侧对齐
    }
 
    Button{                       //Button 用于获取值
        id: getBtn                 //按钮控件,唯一标识ID:getBtn
        text: "获取"                //按钮显示文字
        width: 120                 //按钮宽度
        height: 40                 //按钮高度
 
        anchors.centerIn: parent   //按钮放到窗口中心
 
        onClicked: {               //点击按钮事件;
            label.text = myQmlImp.getValue()
        }
    }
 
    TextField{                      //文字输入控件
        id: textField               //唯一ID
        width: getBtn.width         //也可以直接设置成120
        height: getBtn.height       //也可以直接设置成40
 
        anchors.top: getBtn.bottom  //放到“获取”按钮下方10个像素
        anchors.topMargin: 10
        anchors.left: getBtn.left   //与“获取”按钮左对齐
    }
 
    Button{
        id: setBtn
        text: "设置"
        width: textField.width      //可以设置成getBtn.width或者120
        height: textField.height    //可以设置成getBtn.height或者40
 
        anchors.top: textField.bottom
        anchors.left: textField.left
 
        onClicked: {
            var value = textField.text
            myQmlImp.setValue(value)
        } 
    }  
}

在这里插入图片描述

■ 将C++对象注册到 QML中,在QML使用C++对象(Q_PROPERTY宏 属性绑定)

在 C++ 里定义了一个对象,然后将这个对象注册到 QML 里面。在 QML 里面访问的就是 C++ 定义的对象。

■ C++对象注册到元对象系统

QQmlApplicationEngine::rootContext()->setContextProperty()

■ Q_PROPERTY 宏

使用 Q_PROPERTY 定义交互的属性
Q_PROPERTY:用于声明属性的宏

■ 演示代码

person.h

#ifndef PERSON_H
#define PERSON_H

#include <QObject>

class Person : public QObject
{
    Q_OBJECT
    /* 使用 Q_PROPERTY 定义交互的属性 */
    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)

public:
    explicit Person(QObject *parent = nullptr) : QObject(parent), m_name(""),m_age(0)
    {
    }

    /* 为属性提供 getter 和 setter 方法 */
    QString getName() const { return m_name; }
    void setName(const QString& name) { m_name = name; emit nameChanged(); }

    int getAge() const { return m_age; }
    void setAge(int age) { m_age = age; emit ageChanged(); }

   signals:
       /* 信号与属性对应,通过信号通知其他对象属性的变化 */
       void nameChanged();
       void ageChanged();

   private:
       QString m_name;
       int m_age;
};

#endif // PERSON_H

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "person.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    // 创建Person对象
    Person person;
    QQmlApplicationEngine engine;
    /* 将Person对象作为QML上下文属性 */
    engine.rootContext()->setContextProperty("person", &person);

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5

Window {
    visible: true
    width: 480
    height: 800
    title: qsTr("Hello World")

    Column {
        spacing: 10

        TextField {
            placeholderText: "请输入姓名"
            text: person.name // 与Person对象的name属性绑定
            onTextChanged: person.name = text // 当文本改变时,更新Person对象的name属性
        }

        Slider {
            from: 0
            to: 100
            value: person.age // 与Person对象的age属性绑定
            onValueChanged: person.age = value // 当滑块值改变时,更新Person对象的age属性
        }

        Text {
            text: "姓名:" + person.name
        }

        Text {
            text: "年龄:" + person.age
        }
    }
}

■ 将 C++类注册到 QML,并在QML声明一个对象并进行访问

■ C++类注册到qml中

qmlRegisterType 就是一个函数模板。将 C++ 的类型注册到 QML 系统中,并且带有版本号,方便版本管理。 我们就把main.cpp 中的函数改造一下:

■ 演示代码

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext> 
#include "MyQmlClass.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 
    QGuiApplication app(argc, argv); 
    QQmlApplicationEngine engine; 
//    方式一:注册定义好的对象到 QML
//    MyQmlClass myQmlImp;
//    engine.rootContext()->setContextProperty("myQmlImp", &myQmlImp);
 
//    方式二:注册类到 QML 对象
    qmlRegisterType<MyQmlClass>("com.company.myqmlclass", 1, 0, "MyQmlClass");
 
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
 
    return app.exec();
}

其中:qmlRegisterType 模板函数中的 “com.company.myqmlclass” 为自定义的控件名称类似于C++中的库名称。我们在 QML 中需要 import 这个控件名, “MyQmlClass” 为 C++ 注册的类名, 1和0 为自定义版本号,方便版本管理。
在这里插入图片描述

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.3
import com.company.myqmlclass 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    MyQmlClass{
        id: myQmlImp
    }

    Label{                         //Label用于显示获取C++的值
        id: label                  //显示控件,唯一标识ID:label
        text: ""                   //初始化内容清空

        anchors.bottom: getBtn.top //显示控件的下方放到btn的上方
        anchors.left: getBtn.left  //显示控件的左方与btn的左侧对齐
    }

    Button{                       //Button 用于获取值
        id: getBtn                 //按钮控件,唯一标识ID:getBtn
        text: "获取"                //按钮显示文字
        width: 120                 //按钮宽度
        height: 40                 //按钮高度

        anchors.centerIn: parent   //按钮放到窗口中心

        onClicked: {               //点击按钮事件;
            label.text = myQmlImp.getValue()
        }
    }

    TextField{                      //文字输入控件
        id: textField               //唯一ID
        width: getBtn.width         //也可以直接设置成120
        height: getBtn.height       //也可以直接设置成40

        anchors.top: getBtn.bottom  //放到“获取”按钮下方10个像素
        anchors.topMargin: 10
        anchors.left: getBtn.left   //与“获取”按钮左对齐
    }

    Button{
        id: setBtn
        text: "设置"
        width: textField.width      //可以设置成getBtn.width或者120
        height: textField.height    //可以设置成getBtn.height或者40

        anchors.top: textField.bottom
        anchors.left: textField.left

        onClicked: {
            var value = textField.text
            myQmlImp.setValue(value)
        }
    }
}

■ 将 C++类注册到 QML,信号与槽进行交互

C++ 对象可以发出信号,而QML中的元素可以连接到这些信号上。这样,当C++ 对象的状态发生变化时,可以通过信号与槽机制将这些变化传递给QML界面。

■ C++类注册到qml中

qmlRegisterType 就是一个函数模板。将 C++ 的类型注册到 QML 系统中,并且带有版本号,方便版本管理。 我们就把main.cpp 中的函数改造一下:

■ 演示代码

myobject.h

#include <QObject>
#include <QtDebug>
 
class MyObject : public QObject
{
    Q_OBJECT 
public:
    explicit MyObject(QObject *parent = nullptr) : QObject(parent) {} 
signals:
    void mySignal(QString message); 
public slots:
    void mySlot(const QString& message) { qDebug() << "Received message from QML:" << message; 
    	emit mySignal("Hello from C++");
    }
};

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "myobject.h"
 
int main(int argc, char *argv[])
{
    /* 启用Qt应用程序的高DPI缩放功能 */
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 
    /* 创建一个Qt应用程序的实例 */
    QGuiApplication app(argc, argv);
 
    /* 将自定义 C++ 类型注册到 QML 中的函数*/
    qmlRegisterType<MyObject>("com.example", 1, 0, "MyObject"); 
    
    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    /* 将 QQmlApplicationEngine 对象的 objectCreated 信号连接到一个 lambda 函数上 */
    /* lambda 函数用于在 QML 文件中的根对象被创建时进行处理,检查对象是否成功创建,如果创建失败则退出应用程序 */
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    /* 加载QML文件并显示用户界面 */
    engine.load(url);
 
    return app.exec();
}

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import com.example 1.0
 
Window {
    visible: true
    width: 480
    height: 800
    title: qsTr("Hello World") 
    /* 定义 sendToCpp 信号 */
    signal sendToCpp(string message) 
    /* Connections 组件用于连接 myObject 的 onMySignal 信号 */
    Connections {
        target: myObject
        onMySignal: console.log("Received message from C++:", message)
    }
 
    MyObject {
        id: myObject
        /* 将 onMySignal 信号传递到 sendToCpp信号上,便于 QML 处理 */
        onMySignal: sendToCpp(message)
    }
 
    Button {
        text: "Send message to C++"
        anchors.centerIn: parent
        /* 单击按钮时,会将信号传递到 C++ 的 mySlot 槽上 */
        onClicked: myObject.mySlot("Hello from QML")
    }
}

■ 将C++中的数据模型注册到C++中,qml进行访问 — 模型视图

模型视图(Model-View):可以使用C++ 中的数据模型(QStandardItemModel)来提供数据给QML界面。
QML中的视图元素(如ListView或GridView)可以使用这些模型来显示数据。

■ C++数据模型对象注册到元对象系统

QQmlApplicationEngine::rootContext()->setContextProperty()

■ 演示代码

mymodel.h

#ifndef MYMODEL_H
#define MYMODEL_H
 
#include <QAbstractListModel>
#include <QList>
 
class MyModel : public QAbstractListModel
{
    Q_OBJECT 
public:
    explicit MyModel(QObject *parent = nullptr); 
    enum {
        NameRole = Qt::UserRole + 1,
        AgeRole,
        EmailRole
    };
 
    // 重写以下几个虚函数
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;
 
private:
    struct Person {
        QString name;
        int age;
        QString email;
    }; 
    QList<Person> m_persons;
};
 
#endif // MYMODEL_H

mymodel.cpp

#include "mymodel.h"

MyModel::MyModel(QObject *parent)
    : QAbstractListModel(parent)
{
    // 初始化一些数据
    m_persons.append({"Alice", 25, "alice@example.com"});
    m_persons.append({"Bob", 30, "bob@example.com"});
    m_persons.append({"Charlie", 35, "charlie@example.com"});
}
int MyModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_persons.count();
}
QVariant MyModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if (index.row() >= m_persons.count() || index.row() < 0)
        return QVariant();
    const Person &person = m_persons[index.row()];
    if (role == NameRole)
        return person.name;
    else if (role == AgeRole)
        return person.age;
    else if (role == EmailRole)
        return person.email;
    return QVariant();
}
QHash<int, QByteArray> MyModel::roleNames() const
{
    QHash<int, QByteArray> roles;
    roles[NameRole] = "name";
    roles[AgeRole] = "age";
    roles[EmailRole] = "email";
    return roles;
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "mymodel.h"
 
int main(int argc, char *argv[])
{
    /* 启用Qt应用程序的高DPI缩放功能 */
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 
    /* 创建一个Qt应用程序的实例 */
    QGuiApplication app(argc, argv);
 
    QQmlApplicationEngine engine;
 
    MyModel myModel;
    engine.rootContext()->setContextProperty("myModel", &myModel);
 
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    /* 将 QQmlApplicationEngine 对象的 objectCreated 信号连接到一个 lambda 函数上 */
    /* lambda 函数用于在 QML 文件中的根对象被创建时进行处理,检查对象是否成功创建,如果创建失败则退出应用程序 */
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    /* 加载QML文件并显示用户界面 */
    engine.load(url);
 
    return app.exec();
}

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
 
Window {
    visible: true
    width: 480
    height: 800
    title: qsTr("Hello World")
 
    ListView {
        anchors.fill: parent
        model: myModel
        delegate: Item {
            width: parent.width
            height: 60
            Column {
                Text { text: name }
                Text { text: age }
                Text { text: email }
            }
        }
    }
}

在这里插入图片描述

■ C++使用QML

■ 代码演示

main.qml

import QtQuick 2.7
import QtQuick.Window 2.2
 
Item {
    id: root
    visible: true
    width: 640
    height: 480
    //title: qsTr("Hello World")
 
    property string msg: "I am QML Item"
    signal callCpp(string arg1, string arg2)
 
    MainForm {
        anchors.fill: parent
        mouseArea.onClicked: {
            Qt.quit();
        }
    }
 
    Rectangle {
        anchors.fill: parent
        color: "blue"
        objectName: "rect"
    }
 
    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("onClicked, callCpp")
            root.callCpp(root.msg, "notify cpp")
        }
    }
 
    onHeightChanged: {
        console.log("onHeightChanged execute")
    }
    onWidthChanged: {
        console.log("onWidthChanged execute")
    }
 
 
    //QML中的方法可以被cpp调用,也可以作为槽函数
    function qmlFun(val_arg) {
        console.log("qmlFun execute", val_arg, "return qmlFun_return_result")
        return "qmlFun_return_result"
    }
    //注意槽函数参数为var类型
    function invokeFromCpp(arg1, arg2) {
        console.log("invokeFromCpp execute ", arg1, arg2)
    }
}

cbusiness.h

#ifndef CBUSINESS_H
#define CBUSINESS_H
 
#include <QObject>
 
class CBusiness : public QObject
{
    Q_OBJECT
public:
    explicit CBusiness(QObject *parent = 0);
 
signals:
    void callQml(const QVariant &arg1,const QVariant &arg2);
 
public slots:
    void invokeFromQml(const QString &arg1,const QString &arg2);
};
 
#endif // CBUSINESS_H

cbusiness.cpp

#include "cbusiness.h"
 
#include <QDebug> 
CBusiness::CBusiness(QObject *parent) : QObject(parent)
{ 
} 
void CBusiness::invokeFromQml(const QString &arg1,const QString &arg2)
{
    qDebug() << "CBusiness::" << __FUNCTION__ << arg1 << arg2;
    qDebug() << "CBusiness::" << __FUNCTION__ << " emit callQml";
    emit callQml("I am cpp", "notify qml");
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include <QQuickView>
#include <QQuickItem>
#include <QMetaObject>
#include <QDebug>
 
#include "cbusiness.h"
 
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
 
    QGuiApplication app(argc, argv);
 
    /*
    可以用QQmlComponent\QQuickView\QQuickWidget的C++代码加载QML文档
    当使用QQuickView时,qml的根不能是Window
    */
    QQuickView view(QUrl("qrc:/main.qml"));
    view.show();
 
    // 获取到qml根对象的指针
    QObject *qmlObj = view.rootObject();
 
 
        /*
        修改qml属性值的方法
        QObject::setProperty()  QQmlProperty  QMetaProperty::write()
        */
 
    // 通过QObject设置属性值
    qDebug() << "cpp: " << "set qml property height";
    QQmlProperty(qmlObj, "height").write(500);  //qmlObj->setProperty("height",500);
    // 通过QObject获取属性值
    qDebug() << "cpp: " << "get qml property height" << qmlObj->property("height").toDouble();
    // C++访问qml的其它属性
    qDebug() << "cpp: " << "get qml property msg" << qmlObj->property("msg").toString();
 
 
    // 获取QQuickItem
    QQuickItem *item = qobject_cast<QQuickItem*>(qmlObj);
    // 通过QQuickItem设置属性值
    qDebug() << "cpp: " << "set qml property width";
    item->setWidth(300);
    // 通过QQuickItem获取属性值
    qDebug() << "cpp: " << "get qml property width" << item->width();
 
 
    // 通过object name访问加载的QML对象
    // QObject::findChildren()可用于查找具有匹配object name属性的子项
    QObject *qmlRect = qmlObj->findChild<QObject*>("rect");
    if(qmlRect)
    {
        qDebug() << "cpp: " << "get rect color" << qmlRect->property("color");
    }
 
 
    // C++调用QML方法
    QVariant valReturn;
    QVariant valArg = "I am cpp";
    //Q_RETURN_ARG()和Q_Arg()参数必须制定为QVariant类型
    QMetaObject::invokeMethod(qmlObj, "qmlFun",
                              Q_RETURN_ARG(QVariant,valReturn),
                              Q_ARG(QVariant,valArg));
    qDebug() << "cpp: " << "QMetaObject::invokeMethod result" << valReturn.toString(); //qml函数中返回“ok”
 
 
    CBusiness cppObj;
    // cpp和qml信号与槽关联
    // qml信号绑订cpp的槽,用QString类型
    QObject::connect(qmlObj, SIGNAL(callCpp(QString, QString)), &cppObj, SLOT(invokeFromQml(QString, QString)));
 
    //关联cpp信号与qml槽
    // cpp的信号绑定qml槽,用QVariant类型
    QObject::connect(&cppObj, SIGNAL(callQml(QVariant, QVariant)), qmlObj, SLOT(invokeFromCpp(QVariant, QVariant)));
 
    return app.exec();
}

测试结果
在这里插入图片描述
信号和槽的绑定在c++代码中完成,在c++中可以修改qml的属性,获取qml的属性,调用qml的方法,传递和获取参数均可以

鼠标点击
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/298543.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python 写自动点击爬取数据

今天来点不一样的&#xff01;哥们 提示&#xff1a; 这里只是用于自己学习的 &#xff0c;请勿用违法地方 效果图 会进行点击下一页 进行抓取 需要其他操作也可以自己写 文章目录 今天来点不一样的&#xff01;哥们前言一、上代码&#xff1f;总结 前言 爬虫是指通过编程自动…

软件安全开发

开发背景 软件工程方法&#xff1a; 方法&#xff1a;抽象化、建模、设计、算法、协议 过程&#xff1a;过程的质量、进度、成本、配置 工具&#xff1a;程序设计语言、编译、配置工具 开发模型 瀑布模型 迭代模型 增量模型 原型 螺旋模型 净室模型---范围小&#xf…

Adobe illustrator各版本安装指南

下载链接 https://pan.baidu.com/s/11sTpMUbQEXhyjpkBlixcLg?pwd0531 #2024版 1.鼠标右击【Ai2024(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;【解压到 Ai2024(64bit)】。 2.打开解压后的文件夹&#xff0c;鼠标右击【Setup】选择【以…

配置cendos 安装docker 配置阿里云国内加速

由于我安装的cendos是镜像版。已经被配置好了。所以只需要更新相关配置信息即可。 输入 yum update自动更新所有配置 更新完成后输入 yum list docker-ce --showduplicates | sort -r 自动查询所有可用的docker版本 输入 yum install docker-ce docker-ce-cli container…

[MAUI]在.NET MAUI中调用拨号界面

在.NET MAUI中调用拨号界面 前置要求: Visual Studio 2022 安装包“.NET Multi-platform App UI 开发” 参考文档: 电话拨号程序 新建一个MAUI项目 在解决方案资源管理器窗口中找到Platforms/Android/AndroidManifest.xml在AndroidManifest.xml中添加下文中…块如下:<?xml…

前端uniapp的tab选项卡for循环切换、开通VIP实战案例【带源码/最新】

目录 效果图图1图2 源码最后 这个案例是uniapp&#xff0c;同样也适用Vue项目&#xff0c;语法一样for循环&#xff0c;点击切换 效果图 图1 图2 源码 直接代码复制查看效果 <template><view class"my-helper-service-pass"><view class"tab…

学习笔记——C++中的循环结构 while语句

while循环语句 作用&#xff1a;满足循环条件&#xff0c;执行循环语句 语法&#xff1a;while&#xff08;循环条件&#xff09;{循环语句} 解释&#xff1a;只要循环条件的结果为真&#xff0c;就执行循环语句 以打印0-9这十个数字为例&#xff0c;特别需要注意的是&…

2.3_7 生产者-消费者问题

2.3_7 生产者-消费者问题 系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。(注:这里的“产品”理解为某种数据) 生产者、消费者共享一个初始为空、大小为n的缓冲区。 只有缓冲区没满时,生产者才…

C# Emgu.CV4.8.0读取rtsp流分段保存

【官方框架地址】 https://github.com/emgucv/emgucv 【算法介绍】 EMGU CV&#xff08;Emgu Computer Vision&#xff09;是一个开源的、基于.NET框架的计算机视觉库&#xff0c;它提供了对OpenCV&#xff08;开源计算机视觉库&#xff09;的封装。EMGU CV使得在.NET应用程序…

基于SSM的网上购物平台设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

小游戏实战丨基于Tkinter的五子棋小游戏

文章目录 写在前面Tkinter五子棋系列文章写在后面 写在前面 本期内容&#xff1a;基于tkinter的五子棋小游戏 下载地址&#xff1a;https://download.csdn.net/download/m0_68111267/88700190 实验环境 python3.11及以上pycharmtkinter Tkinter Tkinter是Python的一个标准…

useContext

可以跨组件传值 其实主要的就是三步 1、const xxx React.createContext();创建一个context 2、<xxx.Provider value{{ num, setNum }}>父组件设置要传递的值 3、const { num, setNum } React.useContext(xxx);子组件下使用 特点&#xff1a; 1、可以有多个xxx.Pr…

2024.1.5 关于 二叉平衡树(AVL 树)详解

目录 二叉搜索树 二叉搜索树的简介 二叉搜索树的查找 二叉搜索树的效率 AVL树 AVL 树的简介 AVL 树的实现 AVL树的旋转 右单旋 左单旋 左右双旋 右左双旋 完整 AVL树插入代码 验证 AVL 树 AVL 树的性能 二叉搜索树 要想了解关于二叉平衡树的相关知识&#xff0c;了…

RocketMQ详细介绍及核心问题解释(很全)

1. RocketMq是什么 一个纯Java、分布式队列模型的消息中间件&#xff0c;具有高可用、高可靠、高实时、低延迟的特点。&#xff08;记住这句就行了&#xff09; 2. RocketMq有什么功能 1、业务解耦&#xff1a;这也是发布订阅的消息模型。生产者发送指令到MQ中&#xff0c;然…

三英战吕布web3游戏项目启动全流程

项目是一个学习相关的很好的例子并且开源&#xff0c;原本的项目是连接goerli网络&#xff0c;但我把它修改为可连接ganache网络的项目了&#xff0c;更方便启动。 智能合约部分 进入文件 hardhat.config.js &#xff0c;增加一个钱包私钥 2.执行npm install 3.测试合约 npx ha…

DevSecOps 工具:初学者指南

DevSecOps 是开发、安全和运营的融合&#xff0c;标志着软件开发的范式转变&#xff0c;在整个软件开发生命周期 (SDLC)中无缝集成安全性。 这种方法标志着不再将安全视为开发过程中的一个阶段。除了DevSecOps 的核心原则和最佳实践之外&#xff0c;特定工具也是实施和强化安全…

VMware Workstation——快照

目录 一、为什么要使用快照 二、拍摄快照 三、快照管理 1、克隆 2、转到 ​3、删除 一、为什么要使用快照 VMware虚拟机的快照是一个很重要的功能。 简单点说它相当于某个时刻虚拟的备份&#xff0c;并且可以快速还原至原来的状态。但是它和备份还是有区别的。 【快照…

代码快递员:extern如何送达静态变量至各文件目的地

各位少年&#xff0c;大家好&#xff0c;我是博主那一脸阳光。 前言&#xff1a;话说有一天&#xff0c;静态变量先生和extern女士一起去参加编程界的武林大会。静态变量先生自豪地说&#xff1a;“你知道我为什么这么受欢迎吗&#xff1f;因为我可是个低调的富翁&#xff0c;我…

SpringBoot 如何 配置端口号

结论 server:port: 8088演示 [Ref] 快速构建SpringBoot项目