C++与QML交互总结二

目录

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);
#endifQGuiApplication 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.0Window {width: 640height: 480visible: truetitle: qsTr("qml和cpp交互总结")Item {id: itemanchors.fill: parentQtCtrl.Label {objectName: "qml_label"text: "QML Label"font.pixelSize: 25function 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);
#endifQGuiApplication 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 nullptrauto 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.15Window {width: 640height: 480visible: truetitle: qsTr("qml和cpp交互总结")Item {id: itemanchors.fill: parentQtCtrl.Button {objectName: "qml_button"text: "QML button"font.pixelSize: 25property int cal: 1// qml中自定义信号signal coutNum(int num)onClicked: {OtPerson.showInfo()if (0 == cal++ % 10) {coutNum(cal)}}// cpp的信号绑定qml的槽Connections {target: OtPersonfunction onQmlCall() {console.log("cpp call qml")}}Connections {target: OtPersonfunction 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);
#endifQGuiApplication 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.0Window {width: 640height: 480visible: truetitle: qsTr("qml和cpp交互总结")Item {id: itemanchors.fill: parentQtCtrl.Button {objectName: "qml_button"text: "QML button"font.pixelSize: 25onClicked: {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);
#endifQGuiApplication 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.0Window {width: 640height: 480visible: truetitle: qsTr("qml和cpp交互总结")Item {id: itemanchors.fill: parentQtCtrl.Button {objectName: "qml_button"text: "QML button"font.pixelSize: 25onClicked: {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);
#endifQGuiApplication 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 nullptrauto 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.0Window {width: 640height: 480visible: truetitle: qsTr("qml和cpp交互总结")Item {id: itemanchors.fill: parentQtCtrl.Button {objectName: "qml_button"text: "QML button"font.pixelSize: 25property 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);
#endifQGuiApplication 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 nullptrauto 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.0Window {width: 640height: 480visible: truetitle: qsTr("qml和cpp交互总结")Item {id: itemanchors.fill: parentQtCtrl.Button {objectName: "qml_button"text: tree.name + tree.age + tree.date//Qt.formatDate(tree.date, "yyyy-MM-dd hh:mm:ss")font.pixelSize: 25property int cal: 1// qml中自定义信号signal coutNum(int num)onClicked: {OtPerson.showInfo()if (0 == cal++ % 10) {coutNum(cal)}tree.name = "李四"}// cpp的信号绑定qml的槽Connections {target: OtPersonfunction onQmlCall() {console.log("cpp call qml")}}Connections {target: OtPersonfunction onQmlCall(data) {console.log("cpp call qml " + data)}}}// 使用cpp注入的类型MyTree {id: treename: 'My_Tree'age: 110date: new Date()onNameChanged: {console.log("changed name: " + name)}}}}

3.2QML_ELEMENT

.pro

QT += quickQT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++17 qmltypesQML_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.0SOURCES += \main.cpp \person.cpp \tree.cppRESOURCES += 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 += targetHEADERS += \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);
#endifQGuiApplication 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 nullptrauto 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.0Window {width: 640height: 480visible: truetitle: qsTr("qml和cpp交互总结")Item {id: itemanchors.fill: parentQtCtrl.Button {objectName: "qml_button"text: tree.name + tree.age + tree.date//Qt.formatDate(tree.date, "yyyy-MM-dd hh:mm:ss")font.pixelSize: 25property int cal: 1// qml中自定义信号signal coutNum(int num)onClicked: {OtPerson.showInfo()if (0 == cal++ % 10) {coutNum(cal)}tree.name = "李四"}// cpp的信号绑定qml的槽Connections {target: OtPersonfunction onQmlCall() {console.log("cpp call qml")}}Connections {target: OtPersonfunction onQmlCall(data) {console.log("cpp call qml " + data)}}}// 使用cpp注入的类型Tree {id: treename: 'My_Tree'age: 110date: 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_INVOKABLEQ_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_ELEMENTpublic: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_ANONYMOUSpublic: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_ELEMENTpublic:explicit Person(QObject *parent = nullptr);Person(QString name, int age);// 想要让QML调用函数,函数要加上宏Q_INVOKABLEQ_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);
#endifQGuiApplication 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 nullptrauto 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.0Window {width: 640height: 480visible: truetitle: qsTr("qml和cpp交互总结")Item {id: itemanchors.fill: parentQtCtrl.Button {objectName: "qml_button"text: Person.name + Person.age + Person.datefont.pixelSize: 25property 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: OtPersonfunction onQmlCall() {console.log("cpp call qml")}}Connections {target: OtPersonfunction onQmlCall(data) {console.log("cpp call qml " + data)}}// 使用附加属性:本质上会创建一个附加属性对象Person.name: "赵六"Person.age: 25Person.date: new Date()}}}

.pro

QT += quickQT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++17 qmltypesQML_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.0SOURCES += \main.cpp \person.cpp \tree.cppRESOURCES += 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 += targetHEADERS += \person.h \tree.h

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

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

相关文章

面试题:说一下SpringBoot的自动配置原理

文章目录 引言工作原理剖析EnableAutoConfiguration自动配置生效总结 引言 不论在工作中&#xff0c;亦或是求职面试&#xff0c;Spring Boot已经成为我们必知必会的技能项。除了某些老旧的政府项目或金融项目持有观望态度外&#xff0c;如今的各行各业都在飞速的拥抱这个已经…

c==ubuntu+vscode debug redis7源码

新建.vscode文件夹&#xff0c;创建launch.json和tasks.json {"version": "0.2.0","configurations": [{"name": "C/C Launch","type": "cppdbg","request": "launch","prog…

Flink CDC MySQL同步MySQL错误记录

1、启动 Flink SQL [appuserwhtpjfscpt01 flink-1.17.1]$ bin/sql-client.sh2、新建源表 问题1&#xff1a;Encountered “(” 处理方法&#xff1a;去掉int(11)&#xff0c;改为int Flink SQL> CREATE TABLE t_user ( > uid int(11) NOT NULL AUTO_INCREMENT COMME…

1 论文笔记:Efficient Trajectory Similarity Computation with ContrastiveLearning

2022CIKM 1 intro 1.1 背景 轨迹相似度计算是轨迹分析任务&#xff08;相似子轨迹搜索、轨迹预测和轨迹聚类&#xff09;最基础的组件之一现有的关于轨迹相似度计算的研究主要可以分为两大类&#xff1a; 传统方法 DTW、EDR、EDwP等二次计算复杂度O(n^2)缺乏稳健性 会受到非…

【Linux】进程控制基础知识

目录 一&#xff0c;fack回顾 二&#xff0c;进程终止 1.进程终止&#xff0c;操作系统做了什么&#xff1f; 2.进程终止&#xff0c;常见的方式 1.main函数的&#xff0c;return 返回码 2. exit()函数 三&#xff0c;进程等待 1. 回收进程方法 &#xff08;1. wait…

Node.js 学习笔记

小插件Template String Converter 当输入${}时&#xff0c;自动为其加上 反引号 一、node入门 node.js是什么 node的作用 开发服务器应用 开发工具类应用 开发桌面端应用 1.命令行工具 命令的结构 常用命令 切换到D盘——D: 查看D盘目录——dir 切换工作目录——c…

FFmpeg 命令:从入门到精通 | FFmpeg 音视频处理流程

FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 音视频处理流程 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 音视频处理流程实例 FFmpeg 命令&#xff1a;从入门到精通 | FFmpeg 音视频处理流程 实例 ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx264 -s 1280x…

ElasticSearch - 基于 DSL 、JavaRestClient 实现数据聚合

目录 一、数据聚合 1.1、基本概念 1.1.1、聚合分类 1.1.2、特点 1.2、DSL 实现 Bucket 聚合 1.2.1、Bucket 聚合基础语法 1.2.2、Bucket 聚合结果排序 1.2.3、Bucket 聚合限定范围 1.3、DSL 实现 Metrics 聚合 1.4、基于 JavaRestClient 实现聚合 1.4.1、组装请求 …

XSS详解

XSS一些学习记录 XXS短标签、属性、事件、方法短标签属性事件函数弹窗函数一些对于绕过有用的函数一些函数使用payload收集 浏览器编码问题XML实体编码URL编码JS编码混合编码 一些绕过方法利用constructor原型污染链构造弹框空格绕过圆括号过滤绕过其他的一些绕过 参考 XXS短标…

Zygisk-IL2CppDumper对抗方案

众所周知&#xff0c;Unity引擎中有两种脚本编译器&#xff0c;分别是 Mono 和 IL2CPP 。这两种脚本编译器各有优势&#xff0c;同时也存在一些安全性问题&#xff0c;本文将从游戏安全角度对其进行分析并提供对策。 Mono 是由跨平台的开源.NET 实现&#xff0c;它允许开发者使…

关于 自定义的RabbitMQ的RabbitMessageContainer注解-实现原理

概述 RabbitMessageContainer注解 的主要作用就是 替换掉Configuration配置类中的各种Bean配置&#xff1b; 采用注解的方式可以让我们 固化配置&#xff0c;降低代码编写复杂度、减少配置错误情况的发生&#xff0c;提升编码调试的效率、提高业务的可用性。 为什么说“降低…

PMSM——转子位置估算基于QPLL

文章目录 前言仿真模型观测器速度观测位置观测转矩波形电流波形 前言 今后是电机控制方向的研究生的啦&#xff0c;期待有同行互相交流。 仿真模型 观测器 速度观测 位置观测 转矩波形 电流波形

QSS之QScrollArea

QScrollArea在实际的开发过程中经常使用&#xff0c;主要是有些界面一屏显示不下&#xff0c;所以得用QScorllArea带滚动条拖动显示剩余的界面。默认的QScrollArea滚动条不满设计的风格&#xff0c;因此我们必须设置自已的滚动条风格&#xff0c;QScrollBar分为水平horizontal和…

Spring整合RabbitMQ——生产者

1.生产者整合步骤 添加依赖坐标&#xff0c;在producer和consumer模块的pom文件中各复制一份。 配置producer的配置文件 配置producer的xml配置文件 编写测试类发送消息

2023 年前端 UI 组件库概述,百花齐放!

UI组件库提供了各种常见的 UI 元素&#xff0c;比如按钮、输入框、菜单等&#xff0c;只需要调用相应的组件并按照需求进行配置&#xff0c;就能够快速构建出一个功能完善的 UI。 虽然市面上有许多不同的UI组件库可供选择&#xff0c;但在2023年底也并没有出现一两个明确的解决…

【C++】map、set,multiset和multimap的使用及底层原理【完整版】

目录 一、map和set的使用 1、序列式容器和关联式容器 2、set的使用讲解 3、map的使用讲解 二、multiset和multimap 1、multiset和multimap的使用 2、OJ题&#xff1a;前k个高频单词 一、map和set的使用 1、序列式容器和关联式容器 序列式容器&#xff1a;vector/list/s…

基于微信小程的流浪动物领养小程序设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

CSS 选择器Day01

CSS 定义&#xff1a;层叠样式表(Cascading Style Sheets&#xff0c;缩写为 CSS)&#xff0c;是一种用于定义网页或文档的外观和样式的标记语言。 CSS是一种 样式表 语言&#xff0c;用来描述 HTML 文档的呈现 (美化内容)。它用于控制文本的字体、颜色、间距、布局、背景等各…

如何使用Docker安装最新版本的Redis并设置远程访问(含免费可视化工具)

文章目录 安装Docker安装Redisredis.conf文件远程访问Redis免费可视化工具相关链接Docker是一种开源的应用容器引擎,使用Docker可以让我们快速部署应用环境,本文介绍如何使用Docker安装最新版本的Redis。 安装Docker 首先需要安装Docker,具体的安装方法可以参考Docker官方文…

C++标准模板库STL——list的使用及其模拟实现

1.list的介绍 list的文档介绍 1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。 2. list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向 其前一个…