【Qt- C++ Qml 交互】

news2024/9/30 7:24:12

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的方法,传递和获取参数均可以

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringCloud系列篇:核心组件之负载均衡组件

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringCloud的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.负载均衡组件是什么 二.负载均衡…

PDF文档转换工具箱流量主小程序开发

PDF转换小助手&#xff0c;不仅是文件格式转换的利器&#xff0c;更是一位得力的助手。它精通PDF与各类文档间的自由转换&#xff0c;如Word、Excel、PowerPoint等。 转换选项丰富多样&#xff0c;满足您对文件保护、页面设置、图像品质等细致要求。处理大量文件&#xff1f;…

软件工程:数据流图相关知识和多实例分析

目录 一、数据流图相关知识 1. 基本介绍 2. 常用符号 3. 附加符号 二、数据流图实例分析 1. 活期存取款业务处理系统 2. 工资计算系统 3. 商业自动化系统 4. 学校人事管理系统 5. 教材征订系统 6. 高考录取统分子系统 7. 订货系统 8. 培训中心管理系统 9. 考务处…

模仿Activiti工作流自动建表机制,实现Springboot项目启动后自动创建多表关联的数据库与表的方案

文/朱季谦 熬夜写完&#xff0c;尚有不足&#xff0c;但仍在努力学习与总结中&#xff0c;而您的点赞与关注&#xff0c;是对我最大的鼓励&#xff01; 在一些本地化项目开发当中&#xff0c;存在这样一种需求&#xff0c;即开发完成的项目&#xff0c;在第一次部署启动时&…

【视频图像篇】模糊图像处理之车辆运动造成的字体模糊还原

【视频图像篇】模糊图像处理之车辆运动造成的字体模糊还原 处理车辆运动过程中造成字体模糊重影的图像处理过程—【蘇小沐】 0、目录 1、实验环境 2、路径 3、去运动模糊&#xff08;有噪声&#xff09; 4、其它参数 5、结果展示 1、实验环境 系统环境Windows 11 专业…

phpstudy面板Table ‘mysql.proc‘ doesn‘t exist解决办法

原因分析&#xff1a;误删了mysql数据库 解决办法如下&#xff1a; 1、停止服务 2、先把mysql文件夹下的data文件夹备份&#xff0c;因为data文件里存有数据库文件。然后再删除data文件。 3、cmd管理员命令进入到mysql中的bin目录下 &#xff0c;执行mysqld --initialize-…

Window端口占用处理

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

K8S-应用访问

1 service对象定位 2 Service 实践 手工创建Service 根据应用部署资源对象&#xff0c;创建SVC对象 kubectl expose deployment nginx --port80 --typeNodePortyaml方式创建Service nginx-web的service资源清单文件 apiVersion: v1 kind: Service metadata:name: sswang-ngi…

OpenHarmony底座升级指南(3.2升级4.0)

前言 本文旨在帮助开发者完成底座升级&#xff0c;文中主要以OpenHarmony 3.2 release 升级至OpenHarmony 4.0 release为模板描述。 一、流程概览&#xff1a; 1.1 准备工作 在准备阶段&#xff0c;需要完整收集所有的定制化修改&#xff0c;明确修改人&#xff1b;并且要将…

如何选择最适合的采购付款 (P2P) 解决方案?

无论企业的业务流程执行得如何&#xff0c;流程中始终存在改进空间。更好的管理系统是获得更好结果的关键&#xff0c;尤其是当企业处于增长阶段时。强大的采购到付款&#xff08;P2P&#xff09;系统是加快采购流程&#xff0c;同时保持采购支出可见性的最有效方法之一。 什么…

qml的操作 -- VS2022开发qml,

在使用VS开发软件的时候一般大型软件都会使用模组的方式。每个模组之间独立开发&#xff0c;关于qml写的UI模组也不例外&#xff0c;如果所有的qml都挤在一个文件夹下也不利于管理&#xff0c;维护起来也比较吃力。比较好的管理方法就是按照功能分布存放在不同的文件夹下。还有…

关于“Python”的核心知识点整理大全65

目录 20.2.19 设置 SECRET_KEY 20.2.20 将项目从 Heroku 删除 注意 20.3 小结 附录 A 安装Python A.1.1 确定已安装的版本 A.1.2 在 Linux 系统中安装 Python 3 A.2 在 OS X 系统中安装 Python A.2.1 确定已安装的版本 A.2.2 使用 Homebrew 来安装 Python 3 注意 …

【Docker】docker 服务相关命令

目录 1. 启动docker 服务 2.查看docker 服务的状态 3. 停止docker 服务 4.重启 docker 服务 5.开机自启动命令 1. 启动docker 服务 systemctl start docker 2.查看docker 服务的状态 systemctl status docker 3. 停止docker 服务 systemctl stop docker 此时再使用 syst…

群晖NAS+DMS7.0以上版本+无docker机型安装zerotier

测试机型&#xff1a;群晖synology 218play / DSM版本为7.2.1 因218play无法安装docker&#xff0c;且NAS系统已升级为7.0以上版本&#xff0c;按zerotier官网说法无法安装zerotier, 不过还是可以通过ssh终端和命令方式安装zerotier。 1、在DSM新建文件夹 用于存放zerotier脚…

数据链路层(Data Link Layer)

数据链路层&#xff08;Data Link Layer&#xff09;是计算机网络体系结构中的一层&#xff0c;位于物理层和网络层之间。它的主要功能是在物理传输媒体上建立和管理数据链路。数据链路层的设计和实现对于网络通信的可靠性和效率至关重要。在本文中&#xff0c;我们将探讨数据链…

听GPT 讲Rust源代码--compiler(28)

File: rust/compiler/rustc_codegen_llvm/src/llvm/mod.rs 文件rust/compiler/rustc_codegen_llvm/src/llvm/mod.rs是Rust编译器的LLVM代码生成模块的一个文件。该文件定义了一些用于与LLVM交互的结构体、枚举和常量。 此文件的主要作用是&#xff1a; 定义编译器和LLVM之间的接…

电脑单机游戏推荐:嗜血印 BLOODY SPELL 中文版

《嗜血印》该游戏的故事发生在一个充满秘密和恐怖的江湖中。一伙自称为“灵虚教”的神秘组织闯入万法归宗门派&#xff0c;导致天下大乱。妹妹小鲤被掳为人质&#xff0c;同门师兄弟相继遭到毒手。当嗜血咒印打开的那一刻&#xff0c;重识自我的苏夜锦&#xff0c;为了守护自己…

理想L9自动驾驶域控制器拆解

理想L9自动驾驶域控制器拆解 目录 理想L9自动驾驶域控制器拆解简介&#xff1a;1、SOC-Orin2、MCU-TC3973、交换机4、GMSL解串芯片5、存储 printf("欢迎关注公众号&#xff1a;车载嵌入式探索者&#xff0c;博主建立了一个车规级开发交流群&#xff0c; 感兴趣的朋友可以关…

Linux习题6

解析&#xff1a;排序必须得是rwx,所以B不对 解析&#xff1a; /etc/resolv.conf&#xff1a;是DNS配置文件。在网卡配置文件中进行配置&#xff0c;默认情况下&#xff0c;网卡配置文件DNS优于/etc/resolv.conf。 /etc/hostname&#xff1a;在centos7&#xff0c;配置主机名…

axure rp9添加当前日期、表单添加到中继器

1.[[Now.toLocaleDateString()]] [[Now.toLocaleTimeString()]]当前日期&#xff1a;2024/1/6 13:19:47 2. 输入内容添加到表单&#xff1b; 3.中继器的序号显示&#xff1b; 4. 中继器中添加按钮以及其他的&#xff1b;在中继器中添加动态面板&#xff0c;放入需要添加的按…