C++与QML交互总结二

3 篇文章 0 订阅

目录

1.CPP调用QML

1.1 QMetaObject::invokeMethod调用

1.2 CPP中的信号绑定qml中的槽

2.QML调用CPP

2.1 QML单实例注册

2.2 将类对象注册到QML的上下文中

2.3 QML信号调用CPP槽

3.QML中注入一个cpp实例

3.1qmlRegisterType

3.2QML_ELEMENT

4.附加属性: QML_ATTACHED


以前写过一篇C++和QML交互的的文章(C++与QML交互总结_qml和c++交互_hsy12342611的博客-CSDN博客),很多网友都在看并提出了一些疑问,本篇结合网上的资料从另外一个角度再重新梳理一下C++与QML的交互。

1.CPP调用QML

1.1 QMetaObject::invokeMethod调用

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
// 元对象头文件
#include <QMetaObject>
#include <QDebug>


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    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);

    //cpp调用qml指定对象的指定方法
    auto rootObj = engine.rootObjects();
    // rootObj.first()获取所有对象列表
    auto label = rootObj.first()->findChild<QObject*>("qml_label");

    // 通过元对象调用
    QVariant ret;
    QMetaObject::invokeMethod(label, "getText",
                              Q_RETURN_ARG(QVariant, ret),
                              Q_ARG(QVariant, " hello"));

    qDebug() << ret.toString();

    return app.exec();
}

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QtCtrl
import QtQuick.Layouts 1.0


Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("qml和cpp交互总结")

    Item {
        id: item
        anchors.fill: parent

        QtCtrl.Label {
            objectName: "qml_label"
            text: "QML Label"
            font.pixelSize: 25

            function getText(data) {
                return text + data
            }
        }
    }

}

1.2 CPP中的信号绑定qml中的槽

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
// 元对象头文件
#include <QMetaObject>
#include <QDebug>
#include <QQmlContext>
#include <QAbstractButton>
#include <QPushButton>
#include "person.h"


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    Person person("张三", 18);

    QQmlApplicationEngine engine;
    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);

    //上下文: 将类对象注册到QML的上下文背景中
    auto ctext = engine.rootContext();
    ctext->setContextProperty("OtPerson", &person);

    // 先在上下文注入,再加载
    engine.load(url);

    //cpp获取qml中的指定对象
    auto rootObj = engine.rootObjects();
    // rootObj.first()获取所有对象列表
    auto button = rootObj.first()->findChild<QObject*>("qml_button");
    // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    /*
    // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    auto button = rootObj.first()->findChild<QPushButton*>("qml_button");
    if (!button) {
        qDebug() << "button is nullptr";
    }
    QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
    */


    return app.exec();
}

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QtCtrl
import QtQuick.Layouts 1.0
import QtQml 2.15


Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("qml和cpp交互总结")

    Item {
        id: item
        anchors.fill: parent

        QtCtrl.Button {
            objectName: "qml_button"
            text: "QML button"
            font.pixelSize: 25
            property int cal: 1
            // qml中自定义信号
            signal coutNum(int num)

            onClicked: {
                OtPerson.showInfo()
                if (0 == cal++ % 10) {
                    coutNum(cal)
                }
            }

            // cpp的信号绑定qml的槽
            Connections {
                target: OtPerson
                function onQmlCall() {
                    console.log("cpp call qml")
                }
            }

            Connections {
                target: OtPerson
                function onQmlCall(data) {
                    console.log("cpp call qml " + data)
                }
            }
        }
    }

}

2.QML调用CPP

2.1 QML单实例注册

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
// 元对象头文件
#include <QMetaObject>
#include <QDebug>
#include "person.h"


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    Person person("张三", 18);
    // qml单实例注册
    qmlRegisterSingletonInstance("PersonMudle", 1, 0, "MyPerson", &person);

    QQmlApplicationEngine engine;
    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.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QtCtrl
import QtQuick.Layouts 1.0
import PersonMudle 1.0


Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("qml和cpp交互总结")

    Item {
        id: item
        anchors.fill: parent

        QtCtrl.Button {
            objectName: "qml_button"
            text: "QML button"
            font.pixelSize: 25

            onClicked: {
                MyPerson.showInfo()
            }
        }
    }

}

2.2 将类对象注册到QML的上下文中

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
// 元对象头文件
#include <QMetaObject>
#include <QDebug>
#include <QQmlContext>
#include "person.h"


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    Person person("张三", 18);

    QQmlApplicationEngine engine;
    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);

    //上下文: 将类对象注册到QML的上下文背景中
    auto ctext = engine.rootContext();
    ctext->setContextProperty("OtPerson", &person);

    return app.exec();
}

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QtCtrl
import QtQuick.Layouts 1.0


Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("qml和cpp交互总结")

    Item {
        id: item
        anchors.fill: parent

        QtCtrl.Button {
            objectName: "qml_button"
            text: "QML button"
            font.pixelSize: 25

            onClicked: {
                OtPerson.showInfo()
            }
        }
    }

}

2.3 QML信号调用CPP槽

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
// 元对象头文件
#include <QMetaObject>
#include <QDebug>
#include <QQmlContext>
#include <QAbstractButton>
#include <QPushButton>
#include "person.h"


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    Person person("张三", 18);

    QQmlApplicationEngine engine;
    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);

    //上下文: 将类对象注册到QML的上下文背景中
    auto ctext = engine.rootContext();
    ctext->setContextProperty("OtPerson", &person);

    //cpp获取qml中的指定对象
    auto rootObj = engine.rootObjects();
    // rootObj.first()获取所有对象列表
    auto button = rootObj.first()->findChild<QObject*>("qml_button");
    // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    /*
    // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    auto button = rootObj.first()->findChild<QPushButton*>("qml_button");
    if (!button) {
        qDebug() << "button is nullptr";
    }
    QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clieckButton);
    */


    return app.exec();
}

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QtCtrl
import QtQuick.Layouts 1.0


Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("qml和cpp交互总结")

    Item {
        id: item
        anchors.fill: parent

        QtCtrl.Button {
            objectName: "qml_button"
            text: "QML button"
            font.pixelSize: 25
            property int cal: 1
            // qml中自定义信号
            signal coutNum(int num)

            onClicked: {
                OtPerson.showInfo()
                if (0 == cal++ % 10) {
                    coutNum(cal)
                }
            }
        }
    }

}

3.QML中注入一个cpp实例

3.1qmlRegisterType

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
// 元对象头文件
#include <QMetaObject>
#include <QDebug>
#include <QQmlContext>
#include <QAbstractButton>
#include <QPushButton>
#include "person.h"
#include "tree.h"


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    // 注册一个C++类型到qml中
    qmlRegisterType<Tree>("TreeMudle", 1, 0, "MyTree");

    Person person("张三", 18);

    QQmlApplicationEngine engine;
    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);

    //上下文: 将类对象注册到QML的上下文背景中
    auto ctext = engine.rootContext();
    ctext->setContextProperty("OtPerson", &person);

    // 先在上下文注入,再加载
    engine.load(url);

    //cpp获取qml中的指定对象
    auto rootObj = engine.rootObjects();
    // rootObj.first()获取所有对象列表
    auto button = rootObj.first()->findChild<QObject*>("qml_button");
    // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    /*
    // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    auto button = rootObj.first()->findChild<QPushButton*>("qml_button");
    if (!button) {
        qDebug() << "button is nullptr";
    }
    QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
    */


    return app.exec();
}

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QtCtrl
import QtQuick.Layouts 1.0
import QtQml 2.15
import TreeMudle 1.0


Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("qml和cpp交互总结")

    Item {
        id: item
        anchors.fill: parent

        QtCtrl.Button {
            objectName: "qml_button"
            text: tree.name + tree.age + tree.date//Qt.formatDate(tree.date, "yyyy-MM-dd hh:mm:ss")
            font.pixelSize: 25
            property int cal: 1
            // qml中自定义信号
            signal coutNum(int num)

            onClicked: {
                OtPerson.showInfo()
                if (0 == cal++ % 10) {
                    coutNum(cal)
                }
                tree.name = "李四"
            }

            // cpp的信号绑定qml的槽
            Connections {
                target: OtPerson
                function onQmlCall() {
                    console.log("cpp call qml")
                }
            }

            Connections {
                target: OtPerson
                function onQmlCall(data) {
                    console.log("cpp call qml " + data)
                }
            }
        }

        // 使用cpp注入的类型
        MyTree {
            id: tree
            name: 'My_Tree'
            age: 110
            date: new Date()

            onNameChanged: {
                console.log("changed name: " + name)

            }
        }
    }

}

3.2QML_ELEMENT

.pro

QT += quick

QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17 qmltypes

QML_IMPORT_NAME = TreeMudle
QML_IMPORT_MAJOR_VERSION = 1

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
        person.cpp \
        tree.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    person.h \
    tree.h

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
// 元对象头文件
#include <QMetaObject>
#include <QDebug>
#include <QQmlContext>
#include <QAbstractButton>
#include <QPushButton>
#include "person.h"
#include "tree.h"


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    Person person("张三", 18);

    QQmlApplicationEngine engine;
    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);

    //上下文: 将类对象注册到QML的上下文背景中
    auto ctext = engine.rootContext();
    ctext->setContextProperty("OtPerson", &person);

    // 先在上下文注入,再加载
    engine.load(url);

    //cpp获取qml中的指定对象
    auto rootObj = engine.rootObjects();
    // rootObj.first()获取所有对象列表
    auto button = rootObj.first()->findChild<QObject*>("qml_button");
    // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    /*
    // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    auto button = rootObj.first()->findChild<QPushButton*>("qml_button");
    if (!button) {
        qDebug() << "button is nullptr";
    }
    QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
    */


    return app.exec();
}

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QtCtrl
import QtQuick.Layouts 1.0
import QtQml 2.15
import TreeMudle 1.0


Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("qml和cpp交互总结")

    Item {
        id: item
        anchors.fill: parent

        QtCtrl.Button {
            objectName: "qml_button"
            text: tree.name + tree.age + tree.date//Qt.formatDate(tree.date, "yyyy-MM-dd hh:mm:ss")
            font.pixelSize: 25
            property int cal: 1
            // qml中自定义信号
            signal coutNum(int num)

            onClicked: {
                OtPerson.showInfo()
                if (0 == cal++ % 10) {
                    coutNum(cal)
                }
                tree.name = "李四"
            }

            // cpp的信号绑定qml的槽
            Connections {
                target: OtPerson
                function onQmlCall() {
                    console.log("cpp call qml")
                }
            }

            Connections {
                target: OtPerson
                function onQmlCall(data) {
                    console.log("cpp call qml " + data)
                }
            }
        }

        // 使用cpp注入的类型
        Tree {
            id: tree
            name: 'My_Tree'
            age: 110
            date: new Date()

            onNameChanged: {
                console.log("changed name: " + name)

            }
        }
    }

}

person.h

#ifndef PERSON_H
#define PERSON_H

#include <QObject>
#include <QString>
#include "tree.h"

class Person : public QObject
{
    Q_OBJECT
    //类的附加属性
    QML_ATTACHED(Tree)

public:
    explicit Person(QObject *parent = nullptr);
    Person(QString name, int age);
    // 想要让QML调用函数,函数要加上宏Q_INVOKABLE
    Q_INVOKABLE void showInfo() const noexcept;

public slots:
    void clickButton() const noexcept;
    void clickCal(int data) const noexcept;

signals:
    void qmlCall() const;
    // cpp给qml传参数不是所有类型都可以,一般就字符串,json和基本类型可以
    void qmlCall(QString) const;

private:
    QString _name;
    int _age;

};

#endif // PERSON_H

person.cpp

#include "person.h"
#include <QDebug>

Person::Person(QObject *parent)
    : QObject{parent}
{

}

Person::Person(QString name, int age) {
    _name = name;
    _age = age;
}

void Person::showInfo() const noexcept {
    qDebug() << "name: " << _name << ", age: "<< _age;

    // cpp发送信号调用qml中的槽
    emit qmlCall();
    emit qmlCall("王五");
}

void Person::clickButton() const noexcept {
    qDebug() << __FUNCTION__ << " in qml: click button";
}

void Person::clickCal(int data) const noexcept {
    qDebug() << __FUNCTION__ << "  " << data;
}

tree.h

#ifndef TREE_H
#define TREE_H

#include <QObject>
#include <QDate>
#include <QtQml>

//使用QML_ELEMENT后,就会产生元数据类型:描述数据的数据

class Tree : public QObject
{
    Q_OBJECT
    // qml中使用cpp类的属性
    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
    Q_PROPERTY(QDate date READ getDate WRITE setDate NOTIFY dateChanged)

    QML_ELEMENT

public:
    explicit Tree(QObject *parent = nullptr);
    Tree(QString nme, qint32 age, QDate date);

    void setName(QString name) noexcept;
    void setAge(qint32 age) noexcept;
    void setDate(QDate date) noexcept;

    QString getName() const noexcept;
    qint32 getAge() const noexcept;
    QDate getDate() const noexcept;

signals:
    void nameChanged(QString);
    void ageChanged();
    void dateChanged();

private:
    QString _name;
    qint32 _age;
    QDate _date;
};

#endif // TREE_H

tree.cpp

#include "tree.h"

Tree::Tree(QObject *parent)
    : QObject{parent}
{

}

Tree::Tree(QString name, qint32 age, QDate date) {
    _name = name;
    _age = age;
    _date = date;
}

void Tree::setName(QString name) noexcept {
    _name = name;
    emit nameChanged(name);
}

void Tree::setAge(qint32 age) noexcept {
    _age = age;
    emit ageChanged();
}

void Tree::setDate(QDate date) noexcept {
    _date = date;
    emit dateChanged();
}

QString Tree::getName() const noexcept {
    return _name;
}

qint32 Tree::getAge() const noexcept {
    return _age;
}

QDate Tree::getDate() const noexcept {
    return _date;
}

4.附加属性: QML_ATTACHED

使用附加属性:本质上会创建一个附加属性对象

效果如下:

tree.h

#ifndef TREE_H
#define TREE_H

#include <QObject>
#include <QDate>
#include <QtQml>

//使用QML_ELEMENT后,就会产生元数据类型:描述数据的数据

class Tree : public QObject
{
    Q_OBJECT
    // qml中使用cpp类的属性
    Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
    Q_PROPERTY(QDate date READ getDate WRITE setDate NOTIFY dateChanged)

    QML_ANONYMOUS

public:
    explicit Tree(QObject *parent = nullptr);
    Tree(QString nme, qint32 age, QDate date);

    void setName(QString name) noexcept;
    void setAge(qint32 age) noexcept;
    void setDate(QDate date) noexcept;

    QString getName() const noexcept;
    qint32 getAge() const noexcept;
    QDate getDate() const noexcept;

signals:
    void nameChanged(QString);
    void ageChanged();
    void dateChanged();

private:
    QString _name;
    qint32 _age;
    QDate _date;
};

#endif // TREE_H

tree.cpp

#include "tree.h"

Tree::Tree(QObject *parent)
    : QObject{parent}
{

}

Tree::Tree(QString name, qint32 age, QDate date) {
    _name = name;
    _age = age;
    _date = date;
}

void Tree::setName(QString name) noexcept {
    _name = name;
    emit nameChanged(name);
}

void Tree::setAge(qint32 age) noexcept {
    _age = age;
    emit ageChanged();
}

void Tree::setDate(QDate date) noexcept {
    _date = date;
    emit dateChanged();
}

QString Tree::getName() const noexcept {
    return _name;
}

qint32 Tree::getAge() const noexcept {
    return _age;
}

QDate Tree::getDate() const noexcept {
    return _date;
}

person.h

#ifndef PERSON_H
#define PERSON_H

#include <QObject>
#include <QString>
#include "tree.h"

class Person : public QObject
{
    Q_OBJECT
    //类的附加属性,将Tree中的属性附加到Person类中
    QML_ATTACHED(Tree)
    QML_ELEMENT

public:
    explicit Person(QObject *parent = nullptr);
    Person(QString name, int age);
    // 想要让QML调用函数,函数要加上宏Q_INVOKABLE
    Q_INVOKABLE void showInfo() const noexcept;

public slots:
    void clickButton() const noexcept;
    void clickCal(int data) const noexcept;

    static Tree* qmlAttachedProperties(QObject*);

signals:
    void qmlCall() const;
    // cpp给qml传参数不是所有类型都可以,一般就字符串,json和基本类型可以
    void qmlCall(QString) const;

private:
    QString _name;
    int _age;

};

#endif // PERSON_H

person.cpp

#include "person.h"
#include <QDebug>

Person::Person(QObject *parent)
    : QObject{parent}
{

}

Person::Person(QString name, int age) {
    _name = name;
    _age = age;
}

void Person::showInfo() const noexcept {
    qDebug() << "name: " << _name << ", age: "<< _age;

    // cpp发送信号调用qml中的槽
    emit qmlCall();
    emit qmlCall("王五");
}

void Person::clickButton() const noexcept {
    qDebug() << __FUNCTION__ << " in qml: click button";
}

void Person::clickCal(int data) const noexcept {
    qDebug() << __FUNCTION__ << "  " << data;
}

Tree* Person::qmlAttachedProperties(QObject* obj) {
    qDebug() << __FUNCTION__ << obj;
    return new Tree(obj);
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
// 元对象头文件
#include <QMetaObject>
#include <QDebug>
#include <QQmlContext>
#include <QAbstractButton>
#include <QPushButton>
#include "person.h"
#include "tree.h"


int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    Person person("张三", 18);

    QQmlApplicationEngine engine;
    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);

    //上下文: 将类对象注册到QML的上下文背景中
    auto ctext = engine.rootContext();
    ctext->setContextProperty("OtPerson", &person);

    // 先在上下文注入,再加载
    engine.load(url);

    //cpp获取qml中的指定对象
    auto rootObj = engine.rootObjects();
    // rootObj.first()获取所有对象列表
    auto button = rootObj.first()->findChild<QObject*>("qml_button");
    // 使用QT4的方式绑定信号和槽: qml的信号,cpp的槽
    QObject::connect(button, SIGNAL(clicked()), &person, SLOT(clickButton()));
    QObject::connect(button, SIGNAL(coutNum(int)), &person, SLOT(clickCal(int)));
    /*
    // 使用QT5的方式绑定信号和槽不可行,此处button is nullptr
    auto button = rootObj.first()->findChild<QPushButton*>("qml_button");
    if (!button) {
        qDebug() << "button is nullptr";
    }
    QObject::connect(button, &QAbstractButton::clicked, &person, &Person::clickButton);
    */


    return app.exec();
}

main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QtCtrl
import QtQuick.Layouts 1.0
import QtQml 2.15
import PersonMudle 1.0


Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("qml和cpp交互总结")

    Item {
        id: item
        anchors.fill: parent

        QtCtrl.Button {
            objectName: "qml_button"
            text: Person.name + Person.age + Person.date
            font.pixelSize: 25
            property int cal: 1
            // qml中自定义信号
            signal coutNum(int num)

            onClicked: {
                OtPerson.showInfo()
                if (0 == cal++ % 10) {
                    coutNum(cal)
                }
                console.log(Person.name + " " + Person.age + " " + Person.date)
                console.log(this)
            }

            // cpp的信号绑定qml的槽
            Connections {
                target: OtPerson
                function onQmlCall() {
                    console.log("cpp call qml")
                }
            }

            Connections {
                target: OtPerson
                function onQmlCall(data) {
                    console.log("cpp call qml " + data)
                }
            }

            // 使用附加属性:本质上会创建一个附加属性对象
            Person.name: "赵六"
            Person.age: 25
            Person.date: new Date()
        }
    }

}

.pro

QT += quick

QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17 qmltypes

QML_IMPORT_NAME = PersonMudle
QML_IMPORT_MAJOR_VERSION = 1

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
        person.cpp \
        tree.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    person.h \
    tree.h

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
QMLC++ 交互的过程一般分为以下几个步骤: 1. 定义 C++ 类并注册到 QML 中 你需要在 C++ 中定义一个类,该类封装了你想要实现的功能。同时,你需要使用 `qmlRegisterType` 函数将该类注册到 QML 中,以便在 QML 中使用该类。 例如,你可以定义一个名为 `MyClass` 的类,并将其注册到 QML 中: ```cpp class MyClass : public QObject { Q_OBJECT public: Q_INVOKABLE int myFunction(int arg) { // 实现你的功能 } }; qmlRegisterType<MyClass>("com.example", 1, 0, "MyClass"); ``` 在上面的代码中,`Q_INVOKABLE` 用于声明 `myFunction` 函数可从 QML 中调用,`qmlRegisterType` 函数用于将 `MyClass` 类注册到 QML 中。`"com.example"` 表示注册的命名空间,`1` 和 `0` 表示主版本号和次版本号,`"MyClass"` 是在 QML 中使用的类名。 2. 在 QML 中使用 C++ 类 在 QML 中使用 C++ 类时,你需要使用 `import` 语句导入该类所在的命名空间。然后,你可以通过该命名空间来访问该类。例如: ```qml import com.example 1.0 MyClass { id: myClass } Button { onClicked: { var result = myClass.myFunction(42) // 处理返回值 } } ``` 在上面的代码中,`import` 语句用于导入 `com.example` 命名空间,`MyClass` 用于创建一个 `MyClass` 实例,`id` 属性用于设置实例的标识符,`Button` 用于创建一个按钮,`onClicked` 事件处理程序中调用了 `myFunction` 函数,并处理了它的返回值。 3. 在 C++ 中访问 QML 中的对象 如果你需要从 C++ 中访问 QML 中的对象,你可以使用 `QQuickItem` 类提供的 `findChild` 函数。例如: ```cpp QQuickItem *item = qmlEngine.rootObjects().value(0)->findChild<QQuickItem*>("myItem"); if (item) { // 处理 item 对象 } ``` 在上面的代码中,`qmlEngine.rootObjects()` 函数返回 QML 引擎中所有的根对象,`value(0)` 返回第一个根对象,`findChild` 函数用于查找名为 `"myItem"` 的子对象。 以上就是 QMLC++ 交互的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hsy12342611

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值