import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5 as Controls
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
//Qml通信cpp
Controls.Label
{
objectName: 'labelcpp'
text: 'Qml && cpp'
font.pointSize: 38
//cpp调用这个函数
function getText()
{
return text
}
//加参数后
function getText(info)
{
return text + info
}
}
}
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
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);
//C++调用qml
auto root = engine.rootObjects();//拿到所有对象的列表
//找出列表中的第一个
auto labelqml = root.first()->findChild<QObject*>("labelcpp");//名字要与main.qml中的 objectName: 'labelcpp' 相同
QVariant ret;
//调用上述实例化的名字,main.qml中对应函数名,将返回到上述定义的ret中
QMetaObject::invokeMethod(labelqml, "getText",Q_RETURN_ARG(QVariant, ret));
//如果有参数要传入调用宏Q_ARG(QVariant,"参数")
QMetaObject::invokeMethod(labelqml, "getText",Q_RETURN_ARG(QVariant, ret), Q_ARG(QVariant, " jie"));
qDebug() << ret.toString();
return app.exec();
}
值得注意的是,一般不会使用C++的方法去调用qml中的方法。
下面给这两种方法价绍了如何使用qml创建的按钮调用cpp的槽函数,一种方式是直接在qml调用函数,另一种方式是通过注册信号槽调用
#include "./person.h"
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Person p1("smore", 32);
//方法1:注册一个单例。命名,版本号1.0 对象名,实例对象名
// qmlRegisterSingletonInstance("pModule", 1, 0, "Person", &p1);
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);
//方法2:这种方法在qml文件中会有提示自动补全的功能,直接注册到其中
auto context = engine.rootContext();
context->setContextProperty("Person", &p1);
return app.exec();
}
第一步就完成了,那如何通过注册好以后在qml中如何调用C++的函数?
第二步:就是将调用函数前要加入Q_INVOKABLE 宏,这样这个函数才能够在qml中调用
最后一步,通过在main.cpp中注册某个类,通过这个注册好的版本号引入对应要调用的qml文件中,然后直接通过 类.函数 调用对应的函数
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5 as Controls
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Controls.Button
{
text: 'Button1'
onClicked: Person.printInfo()
}
}
#ifndef PERSON_H
#define PERSON_H
#include
#include
class Person : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Person(QString name, quint8 age);
Q_INVOKABLE void printInfo()const noexcept;
private:
QString m_name;
quint8 m_age;
};
#endif // PERSON_H
=============
#include "person.h"
#include
Person::Person(QString name, quint8 age) : m_name(name), m_age(age)
{
}
void Person::printInfo()const noexcept
{
qDebug() << "name: " << m_name <<" age: " << m_age;
}
在person头文件中注册槽函数
public slots:
void slotInfo()const noexcept;
实现方法
void Person::slotInfo()const noexcept
{
qDebug() << __FUNCTION__ << "this is slot function";
}
主函数中调用
其中,要通过调用引擎获取到对应的按钮,然后通过这个按钮写信号槽的连接connect函数
//C++调用qml
Person p1("smore", 32);
auto root = engine.rootObjects();
auto pushButton = root.first()->findChild<QObject*>("smoreButton");
//比较好用的一种
QObject::connect(pushButton,SIGNAL(clicked()), &p1, SLOT(slotInfo()));
QML源文件实现方法
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5 as Controls
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Controls.Button
{
objectName: "smoreButton"
text: 'Button1'
onClicked: Person.printInfo()
}
}
总结:就是在qml中注册按钮后在cpp中使用信号槽的方式,前提是先获取到按钮和对象。
还有一种方式:直接在qml中写入信号,通过这个信号调用cpp中的函数槽方法:
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5 as Controls
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Controls.Button
{
objectName: "smoreButton"
property int count: 0
signal signalInfo(int count)
text: 'Button1'
onClicked:
{
Person.printInfo();
++count;
if(count % 2 === 0)
signalInfo(count);
}
}
}
person类
#ifndef PERSON_H
#define PERSON_H
#include
#include
class Person : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Person(QString name, quint8 age);
Q_INVOKABLE void printInfo()const noexcept;
public slots:
void slotInfo(int count)const noexcept;
private:
QString m_name;
quint8 m_age;
};
#endif // PERSON_H
#include "person.h"
#include
Person::Person(QString name, quint8 age) : m_name(name), m_age(age)
{
}
void Person::printInfo()const noexcept
{
qDebug() << "name: " << m_name <<" age: " << m_age;
}
void Person::slotInfo(int count)const noexcept
{
qDebug() << __FUNCTION__ << "this is slot function" << count;
}
main.cpp
#include "./person.h"
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Person p1("smore", 32);
// qmlRegisterSingletonInstance("pModule", 1, 0, "Person", &p1);
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);
auto context = engine.rootContext();
context->setContextProperty("Person", &p1);
//C++调用qml
auto root = engine.rootObjects();
auto pushButton = root.first()->findChild<QObject*>("smoreButton");
QObject::connect(pushButton,SIGNAL(signalInfo(int)), &p1, SLOT(slotInfo(int)));
return app.exec();
}
上面这两种,一种是
signals:
void signalQmlCall() const;
//void signalQmlCall(QString) const;
void Person::printInfo()const noexcept
{
qDebug() << "name: " << m_name <<" age: " << m_age;
emit signalQmlCall();
//emit signalQmlCall(m_name);
}
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5 as Controls
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Controls.Button
{
objectName: "smoreButton"
property int count: 0
signal signalInfo(int count)
text: 'Button1'
onClicked:
{
Person.printInfo();
}
}
Connections
{
target: Person
function onSignalQmlCall()
//function onSignalQmlCall(value)
{
console.log('cpp signal')
console.log('cpp signal',value)
}
}
}
输出
name: “smore” age: 32
qml: cpp signal
其余方式与上述(2)中的代码一样
这种就是调用对应类中的函数方法在qml
第一种方法:
前言 : 这个过程通过在qml中设置对应的属性值再从cpp中的方法函数中调用对应的函数
遇到的错误:
qml调用function方法函数的时候开头字母不能大写;
quint32 设置年龄的时候如果设置成quint8 或者quint64 都会报错,应该是quint8 代表的不是int类型,代表的是unchar类型,quint64不知道是为什么
main.cpp
#include "./person.h"
#include
#include
#include
#include
#include
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("smore", 32);
qmlRegisterType<Info>("smoreModule", 1, 0, "Info");//注入一个类型到qml文档中,这样qml中才能调用Info这个类qml文档中
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);
auto context = engine.rootContext();
context->setContextProperty("Person", &person);
engine.load(url);
return app.exec();
}
main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import smoreModule 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Button
{
objectName: "jieButton"
text: 'click' + info.name + ' ' + info.age + ' ' + Qt.formatDateTime(info.date,'yyyy-MM-dd hh:mm:ss')
onClicked:
{
Person.printInfo();
}
}
Connections
{
target: Person
function onqmlCall(value)
{
console.log('cpp signal',value)
}
}
Info{
id: info
name: 'smart'
age: 1
date: new Date()
}
}
person类
#ifndef PERSON_H
#define PERSON_H
#include
#include
#include
class Info : public QObject
{
Q_OBJECT
//注册一个属性,才能在qml中调用出来
Q_PROPERTY(QString name READ getName WRITE setName NOTIFY signalname)
Q_PROPERTY(quint64 age READ getAge WRITE setAge NOTIFY signalage)
Q_PROPERTY(QDate date READ getDate WRITE setDate NOTIFY signaldate)
public:
using QObject::QObject;
void setName(QString name)noexcept;
QString getName() const noexcept;
void setAge(quint32 age) noexcept;
quint32 getAge() const noexcept;
void setDate(QDate date)noexcept;
QDate getDate() const noexcept;
signals:
void signalname();
void signalage();
void signaldate();
private:
QString m_name;
quint32 m_age;
QDate m_date;
};
class Person : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Person(QString name, quint8 age);
Q_INVOKABLE void printInfo()const noexcept;// qml call
signals:
void qmlCall(QString) const;
private:
QString m_name;
quint8 m_age;
};
#endif // PERSON_H
#include "person.h"
#include
Person::Person(QString name, quint8 age) : m_name(name), m_age(age)
{
}
void Person::printInfo()const noexcept
{
qDebug() << "name: " << m_name <<" age: " << m_age;
emit qmlCall(m_name);
}
void Info::setName(QString name) noexcept
{
m_name= qMove(name);
emit signalname();
}
QString Info::getName() const noexcept
{
return m_name;
}
void Info::setAge(quint32 age) noexcept
{
m_age = age;
emit signalage();
}
quint32 Info::getAge() const noexcept
{
return m_age;
}
void Info::setDate(QDate date) noexcept
{
m_date = date;
emit signaldate();
}
QDate Info::getDate() const noexcept
{
return m_date;
}
第二中方法:
Q_ELEMENT的这种方法QT自己找不到对应文件,先搁置起来