一、代码逐行详解(Qt QML调用C++注册类)
1. backendclass.h(C++后端类头文件)
cpp
#ifndef BACKENDCLASS_H // 防止头文件重复包含(头文件保护宏)
#define BACKENDCLASS_H
#include <QObject> // 必须包含,因为BackendClass继承QObject(Qt核心对象类)
#include <QQmlEngine> // 包含qmlRegisterType所需的头文件
// 自定义后端类,继承QObject才能被QML识别(Qt元对象系统要求)
class BackendClass : public QObject
{
Q_OBJECT // 必须添加,启用Qt元对象系统(信号槽、属性、Q_INVOKABLE等)
public:
// 构造函数:explicit防止隐式转换,parent参数用于Qt父子对象内存管理
explicit BackendClass(QObject *parent = nullptr);
// Q_INVOKABLE:标记该函数可被QML直接调用
Q_INVOKABLE int getnum();
Q_INVOKABLE void printSomething();
// 静态函数:用于注册类到QML引擎(静态函数无需实例化即可调用)
static void registerClass();
signals: // 信号声明区(本例暂无自定义信号)
};
#endif // BACKENDCLASS_H // 头文件保护宏结束
2. backendclass.cpp(C++后端类实现文件)
cpp
#include "backendclass.h" // 包含自定义头文件
#include <QtDebug> // 包含qInfo()等日志函数所需头文件
// 构造函数实现:调用父类QObject的构造函数
BackendClass::BackendClass(QObject *parent) : QObject(parent)
{
// 构造函数体为空,本例无需初始化逻辑
}
// getnum函数实现:返回整型值42,供QML调用获取数据
int BackendClass::getnum()
{
return 42;
}
// printSomething函数实现:输出日志,供QML点击按钮触发
void BackendClass::printSomething()
{
qInfo()<<"hello world"; // Qt日志输出函数,替代printf/cout,跨平台
}
// 注册类到QML的静态函数实现
void BackendClass::registerClass()
{
// qmlRegisterType:将C++类注册为QML可识别的类型
// 参数说明:
// 1. 命名空间"com.reddit"(QML中通过import引入)
// 2. 主版本号1
// 3. 次版本号0
// 4. QML中使用的类名"BackendClass"
qmlRegisterType<BackendClass>("com.reddit",1,0,"BackendClass");
}
3. main.cpp(程序入口文件)
cpp
#include <QGuiApplication> // Qt GUI应用程序核心类(处理事件循环、窗口等)
#include <QQmlApplicationEngine> // 加载和管理QML文件的引擎类
#include <QQmlContext> // QML上下文类(用于设置上下文属性)
#include "backendhelper.h" // 自定义辅助类(本例未使用,可忽略)
#include "backendclass.h" // 包含自定义后端类头文件
int main(int argc, char *argv[])
{
// 启用高DPI缩放,适配不同分辨率屏幕(Qt高DPI适配)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
// 创建GUI应用程序对象:argc/argv是命令行参数,管理应用程序生命周期
QGuiApplication app(argc, argv);
// 创建QML引擎对象:负责加载、解析、运行QML文件
QQmlApplicationEngine engine;
// 创建BackendHelper实例(本例未使用,可删除)
BackendHelper obj;
// 调用静态函数:将BackendClass注册到QML引擎
BackendClass::registerClass();
// 设置上下文属性:将C++对象暴露给QML(本例obj未使用,仅演示语法)
// 参数1:上下文属性名(QML中用cBackendHelper访问)
// 参数2:C++对象指针(生命周期需大于QML引擎)
engine.rootContext()->setContextProperty("cBackendHelper",&obj);
// 定义QML文件路径:qrc:/表示资源文件路径(需在pro文件中配置资源)
const QUrl url(QStringLiteral("qrc:/main.qml"));
// 连接信号:监听QML引擎的objectCreated信号(QML对象创建完成/失败时触发)
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
// 回调函数逻辑:如果QML对象创建失败且是主窗口url,退出应用
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection); // 队列连接:跨线程安全,事件循环中执行
// 加载QML主文件:启动QML界面
engine.load(url);
// 启动应用程序事件循环:阻塞直到应用退出(如关闭窗口)
return app.exec();
}
4. main.qml(QML界面文件)
qml
import QtQuick 2.12 // 导入QtQuick核心模块(基础UI元素:矩形、文本、按钮等)
import QtQuick.Controls 2.5// 导入QtQuick控件模块(按钮、窗口等高级控件)
import com.reddit 1.0 // 导入自定义C++类的命名空间(对应qmlRegisterType的参数)
// 应用程序窗口:QML根元素,提供窗口属性(大小、标题、可见性)
ApplicationWindow {
id: window // 唯一标识,用于内部引用
visible: true // 窗口是否可见
width: 640 // 窗口宽度
height: 480 // 窗口高度
title: qsTr("Stack") // 窗口标题,qsTr支持国际化
// 实例化注册的C++类:对应qmlRegisterType的BackendClass
BackendClass{
id:myBackend; // QML中引用该实例的标识
}
// 文本控件:显示C++返回的数值
Text{
id:mytext // 文本控件标识
anchors.centerIn: parent // 居中对齐父元素(ApplicationWindow)
font.pointSize: 15 // 字体大小
// 调用C++的getnum()函数:Q_INVOKABLE标记后可直接调用
text: myBackend.getnum()
}
// 按钮控件:点击触发C++函数
Button{
id:myButton // 按钮标识
text: "Click Me" // 按钮显示文本
anchors.top: mytext.bottom // 锚点:按钮顶部对齐文本底部
anchors.horizontalCenter:parent.horizontalCenter // 水平居中
anchors.topMargin: 10 // 与文本的顶部间距
// 点击事件:调用C++的printSomething()函数
onClicked: myBackend.printSomething()
}
}
二、CSDN笔记版(可直接复制发布)
标题:Qt QML调用C++注册类(零基础入门实战)
前言
作为Qt新手,本文详细讲解如何将C++类注册到QML引擎,并实现QML调用C++函数的完整流程,包含完整代码和逐行解析,适合刚接触Qt QML的同学。
一、核心知识点
- Qt元对象系统 :
Q_OBJECT宏是核心,启用信号槽、Q_INVOKABLE、属性等功能; - qmlRegisterType:将C++类注册为QML可实例化的类型(区别于上下文属性);
- Q_INVOKABLE:标记C++函数可被QML直接调用;
- QML与C++交互:两种核心方式(注册类+上下文属性),本文重点讲注册类。
二、完整代码实现
1. 工程结构
├── backendclass.h // C++后端类头文件
├── backendclass.cpp // C++后端类实现
├── main.cpp // 程序入口
├── main.qml // QML界面
└── xxx.pro // 工程文件(需添加QT += core gui qml quick controls2)
2. 工程文件(xxx.pro)
qmake
QT += core gui qml quick controls2
CONFIG += c++11
SOURCES += main.cpp \
backendclass.cpp
HEADERS += backendclass.h
RESOURCES += qml.qrc # 需创建资源文件,包含main.qml
3. 资源文件(qml.qrc)
xml
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>
4. 核心代码(同上文逐行解析的4个文件,直接复制即可)
三、代码逐行解析
(复制上文"一、代码逐行详解"的内容,保留格式)
四、运行效果
- 启动程序后,窗口居中显示文本"42"(C++的getnum()返回值);
- 点击"Click Me"按钮,控制台输出"hello world"(C++的printSomething()函数)。
五、新手常见问题&解决
- qInfo()报错"incomplete return type" :缺少
#include <QtDebug>头文件; - QML找不到BackendClass :检查
qmlRegisterType的命名空间和版本号,QML中import需完全匹配; - QML调用C++函数无响应 :忘记加
Q_INVOKABLE宏,或函数未实现; - 程序闪退:C++对象生命周期短于QML引擎(注册类方式无此问题,上下文属性需注意)。
六、扩展知识点
- 注册类 vs 上下文属性 :
- 注册类(qmlRegisterType):QML中可多次实例化,适合自定义控件;
- 上下文属性(setContextProperty):全局单例,适合全局数据/工具类;
- 信号槽交互:C++发送信号,QML接收;或QML发送信号,C++接收(需用signals和slots);
- 属性绑定 :用
Q_PROPERTY定义C++属性,QML可直接绑定(如text: myBackend.num)。
三、关键点回顾
- 核心前提 :C++类必须继承
QObject并添加Q_OBJECT宏,才能被QML识别; - 注册类 :通过
qmlRegisterType将C++类注册到QML命名空间,QML中import后可实例化; - 函数调用 :C++函数需加
Q_INVOKABLE标记,才能被QML直接调用; - 工程配置 :pro文件需添加
QT += qml quick controls2,并配置资源文件包含QML。
没问题!我为你打造一份超详细版CSDN笔记,不仅逐行解析代码,还补充新手必懂的背景知识、工程配置、运行步骤、常见坑点和调试方法,完全适配零基础同学的学习节奏~
【零基础入门】Qt QML调用C++注册类(万字详解)
一、前置知识(新手必看)
在开始代码解析前,先搞懂几个核心概念,避免"只抄代码不懂原理":
- Qt元对象系统(MOC) :Qt的核心机制,通过
Q_OBJECT宏实现信号槽、反射(QML调用C++的底层原理),所有被QML调用的C++类必须继承QObject并加Q_OBJECT。 - QML与C++交互的两种核心方式 :
- 方式1:
qmlRegisterType(本文重点):将C++类注册为QML的"可实例化类型",QML中可像普通组件一样<BackendClass id=xxx/>创建多个实例; - 方式2:
setContextProperty:将C++对象暴露为QML的"全局单例",QML中直接用cBackendHelper.xxx()调用,适合全局工具类。
- 方式1:
- 工程文件(.pro)的作用:Qt的工程配置文件,告诉编译器"要编译哪些文件、依赖哪些Qt模块、去哪里找头文件"。
二、完整工程搭建(从0到1)
步骤1:创建Qt工程
打开Qt Creator → 新建项目 → 选择"Qt Quick Application - Empty" → 填写项目名称(如QmlCallCpp)→ 选择Qt版本(建议5.15+)→ 完成。
步骤2:配置工程文件(QmlCallCpp.pro)
qmake
# 核心:添加QML/Quick/控件模块(必须!否则找不到QML相关类)
QT += core gui qml quick controls2
# 指定C++版本(Qt5推荐C++11,Qt6默认C++17)
CONFIG += c++11
# 禁用Qt旧版本兼容性警告(新手可忽略)
DEFINES += QT_DEPRECATED_WARNINGS
# 源文件:告诉编译器要编译哪些.cpp文件
SOURCES += \
main.cpp \
backendclass.cpp
# 头文件:告诉编译器头文件路径
HEADERS += \
backendclass.h
# 资源文件:将QML文件打包到程序中(必须!否则运行找不到main.qml)
RESOURCES += qml.qrc
# 默认应用程序图标(新手可忽略)
# RC_ICONS = appicon.ico
步骤3:创建资源文件(qml.qrc)
右键项目 → 添加新文件 → 选择"Qt - Qt Resource File" → 命名为qml.qrc → 打开后添加前缀(默认/)→ 添加文件 → 选中main.qml(后续创建)。
最终qml.qrc内容:
xml
<RCC>
<qresource prefix="/">
<!-- 将main.qml添加到资源中,路径为qrc:/main.qml -->
<file>main.qml</file>
</qresource>
</RCC>
三、核心代码逐行解析(带背景+原理)
1. backendclass.h(C++后端类头文件)
cpp
// 头文件保护宏:防止同一个头文件被多次#include(编译报错)
// 原理:第一次包含时定义BACKENDCLASS_H,后续包含时跳过整个文件
#ifndef BACKENDCLASS_H
#define BACKENDCLASS_H
// 必须包含QObject:所有Qt对象的基类,提供元对象系统支持
#include <QObject>
// 必须包含QQmlEngine:qmlRegisterType函数的声明在这个头文件里
#include <QQmlEngine>
// 自定义类继承QObject:这是QML调用C++的前提(元对象系统依赖)
class BackendClass : public QObject
{
// 核心宏:启用Qt元对象系统(MOC工具会扫描这个宏,生成额外代码)
// 没有这个宏:Q_INVOKABLE、信号槽、qmlRegisterType全部失效!
Q_OBJECT
public:
// 构造函数:
// - explicit:禁止隐式类型转换(Qt推荐写法,避免意外bug)
// - QObject *parent = nullptr:Qt父子对象机制,父对象销毁时自动销毁子对象
// (防止内存泄漏,比如BackendClass实例被QML持有后,QML销毁时会自动释放)
explicit BackendClass(QObject *parent = nullptr);
// Q_INVOKABLE:标记该函数可被QML调用
// 原理:将函数注册到Qt元对象系统,QML通过反射调用
// 注意:函数参数/返回值必须是QML支持的类型(int/string/QVariant等)
Q_INVOKABLE int getnum();
Q_INVOKABLE void printSomething();
// 静态函数:用于注册C++类到QML引擎
// 静态函数的优势:无需创建BackendClass实例即可调用(main函数中直接用BackendClass::registerClass())
static void registerClass();
signals:
// 信号声明区:用于C++主动通知QML(本例暂未使用,后续扩展会讲)
// 信号语法:void 信号名(参数); 无需实现,由MOC自动生成
// 示例:void numChanged(int newNum);
};
// 头文件保护宏结束
#endif // BACKENDCLASS_H
2. backendclass.cpp(C++后端类实现文件)
cpp
// 包含自定义头文件:必须!否则编译器找不到BackendClass的声明
#include "backendclass.h"
// 包含QtDebug:qInfo()/qDebug()等日志函数的头文件
// 新手坑:忘记加这个头文件会报"incomplete return type"错误
#include <QtDebug>
// 构造函数实现:
// 冒号后面是"初始化列表",调用父类QObject的构造函数
// 原理:子类构造时必须先构造父类,Qt对象的parent机制依赖这个
BackendClass::BackendClass(QObject *parent) : QObject(parent)
{
// 构造函数体:本例无需初始化逻辑,可留空
// 示例:如果有成员变量,可在这里初始化,比如m_num = 42;
}
// getnum函数实现:返回整型值42
// QML调用这个函数时,会拿到返回值并显示在界面上
int BackendClass::getnum()
{
// 新手扩展:可以在这里加日志,调试是否被调用
qDebug() << "getnum()被QML调用了!返回值:42";
return 42;
}
// printSomething函数实现:输出日志
// QML点击按钮时调用这个函数,控制台会打印hello world
void BackendClass::printSomething()
{
// qInfo():Qt跨平台日志函数,比printf/cout更友好(支持不同颜色、日志级别)
// 输出位置:Qt Creator的"应用程序输出"面板
qInfo() << "hello world(来自C++的打印)";
}
// 注册C++类到QML的核心函数
void BackendClass::registerClass()
{
// qmlRegisterType<C++类名>("命名空间", 主版本号, 次版本号, "QML中使用的类名")
// 核心原理:告诉QML引擎"有一个C++类可以在QML中像普通组件一样使用"
// 新手注意:
// 1. 命名空间建议用"公司域名反转"(如com.xxx),避免冲突;
// 2. 版本号与QML中的import必须完全匹配(比如import com.reddit 1.0);
// 3. QML类名首字母大写(Qt规范);
qmlRegisterType<BackendClass>("com.reddit", 1, 0, "BackendClass");
}
3. main.cpp(程序入口文件)
cpp
// QGuiApplication:Qt GUI应用的核心类,管理应用生命周期、事件循环、窗口等
// 区别:Qt Console Application用QCoreApplication(无GUI)
#include <QGuiApplication>
// QQmlApplicationEngine:加载和管理QML文件的引擎(核心!没有它QML无法运行)
#include <QQmlApplicationEngine>
// QQmlContext:QML上下文类,用于设置全局属性(本例obj未使用,仅演示)
#include <QQmlContext>
// 自定义辅助类(本例未使用,可删除,新手别被干扰)
#include "backendhelper.h"
// 包含自定义后端类头文件
#include "backendclass.h"
// 程序入口函数:所有C++程序的起点
int main(int argc, char *argv[])
{
// 高DPI适配:启用Qt的高分辨率屏幕支持(比如4K屏不会模糊)
// Qt5必须加,Qt6默认启用(可省略)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
// 创建应用程序对象:
// - argc/argv:命令行参数(比如运行时传参);
// - 这个对象是Qt应用的"心脏",管理所有资源和事件循环;
QGuiApplication app(argc, argv);
// 创建QML引擎对象:负责加载、解析、执行QML文件
QQmlApplicationEngine engine;
// 创建BackendHelper实例(本例未使用,可删除)
// 新手注意:如果用setContextProperty暴露对象,要确保对象生命周期≥QML引擎
BackendHelper obj;
// 调用静态函数:注册C++类到QML引擎
// 必须在load QML之前调用!否则QML找不到BackendClass
BackendClass::registerClass();
// 设置QML全局上下文属性(本例仅演示,obj未使用)
// 语法:engine.rootContext()->setContextProperty("QML中使用的名称", C++对象指针)
// 区别于qmlRegisterType:这个是"全局单例",QML中直接用cBackendHelper.xxx()调用
engine.rootContext()->setContextProperty("cBackendHelper", &obj);
// 定义QML文件路径:
// - QStringLiteral:Qt优化宏,避免字符串拷贝(新手可直接写"qrc:/main.qml");
// - qrc:/:表示资源文件路径(对应qml.qrc中的prefix);
// 新手坑:如果路径写错,程序会闪退,且提示"Could not load qrc:/main.qml"
const QUrl url(QStringLiteral("qrc:/main.qml"));
// 连接信号:监听QML对象创建状态(新手可先理解,不用深究)
// 原理:QML引擎加载QML文件后,会触发objectCreated信号,告诉我们"QML对象是否创建成功"
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
// 回调函数逻辑:
// - 如果obj为空(QML创建失败),且失败的是主窗口url(qrc:/main.qml),则退出应用
// - 避免程序"假死"(窗口没出来,但进程还在运行)
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection); // 队列连接:跨线程安全(新手默认用这个即可)
// 加载QML主文件:QML引擎开始解析并显示界面
// 这行代码执行后,QML的ApplicationWindow就会显示出来
engine.load(url);
// 启动应用程序事件循环:
// - 阻塞函数,直到应用退出(比如关闭窗口、调用quit());
// - 事件循环:处理鼠标点击、键盘输入、定时器等所有事件;
// - 返回值:应用退出码(0表示正常退出,非0表示异常)
return app.exec();
}
4. main.qml(QML界面文件)
qml
// 导入QtQuick核心模块:提供基础UI元素(Text、Button、Rectangle等)
// 版本号2.12:需与Qt版本匹配(Qt5.12+支持,新手别改)
import QtQuick 2.12
// 导入QtQuick控件模块:提供高级控件(ApplicationWindow、Button、TextField等)
import QtQuick.Controls 2.5
// 导入自定义C++类的命名空间:
// 必须与qmlRegisterType的参数完全匹配(com.reddit 1.0)
// 新手坑:版本号写错(比如1.1)会报"Module com.reddit is not installed"
import com.reddit 1.0
// ApplicationWindow:QtQuick.Controls提供的顶级窗口组件
// 替代QtQuick的Window,增加了标题栏、菜单等原生窗口特性
ApplicationWindow {
id: window // QML元素的唯一标识:内部可通过window.xxx引用(比如window.width)
visible: true // 窗口是否可见(必须设为true,否则窗口不显示)
width: 640 // 窗口宽度(像素)
height: 480 // 窗口高度(像素)
title: qsTr("Stack")// 窗口标题:qsTr()支持国际化(新手可直接写"Stack")
// 实例化注册的C++类:
// 语法与QML原生组件一致(比如Rectangle{}),id用于内部调用
// 原理:QML引擎通过反射创建BackendClass的实例,生命周期与window一致
BackendClass{
id: myBackend // 唯一标识,QML中通过myBackend.xxx()调用C++函数
}
// Text控件:显示文本(本例显示C++返回的42)
Text{
id: mytext // 文本控件标识
// 锚点布局(QML核心布局方式):居中对齐父元素(window)
// 替代:x: (window.width - width)/2; y: (window.height - height)/2
anchors.centerIn: parent
font.pointSize: 15 // 字体大小(像素)
// 调用C++的getnum()函数:
// 原理:QML通过元对象系统调用C++的Q_INVOKABLE函数,拿到返回值后显示
// 新手注意:函数名要写对(区分大小写),否则报"Property 'getnum' not found"
text: myBackend.getnum()
}
// Button控件:点击触发C++函数
Button{
id: myButton // 按钮标识
text: "Click Me"// 按钮显示的文本
// 锚点布局:按钮顶部对齐文本底部
anchors.top: mytext.bottom
// 水平居中对齐父元素
anchors.horizontalCenter: parent.horizontalCenter
// 与文本的顶部间距(像素)
anchors.topMargin: 10
// 点击事件:QML的信号槽(onClicked是Button的点击信号)
// 触发时调用C++的printSomething()函数
onClicked: myBackend.printSomething()
}
}
四、运行步骤&效果验证
步骤1:编译运行
点击Qt Creator的"运行"按钮(绿色三角)→ 等待编译完成 → 程序启动。
步骤2:验证效果
-
界面效果:窗口居中显示文本"42",下方有"Click Me"按钮;
-
点击按钮 :Qt Creator的"应用程序输出"面板会打印:
getnum()被QML调用了!返回值:42 hello world(来自C++的打印)
五、新手常见坑点&解决方案(避坑指南)
| 坑点现象 | 原因 | 解决方案 |
|---|---|---|
| qInfo()报错"incomplete return type" | 缺少<QtDebug>头文件 |
在backendclass.cpp中添加#include <QtDebug> |
| QML报"Module com.reddit is not installed" | import版本号与qmlRegisterType不匹配,或未调用registerClass() | 1. 检查import版本(比如1.0);2. 确保main函数中load QML前调用BackendClass::registerClass() |
| QML报"Property 'getnum' not found" | 1. C++函数没加Q_INVOKABLE;2. 函数名拼写错误(区分大小写) | 1. 给getnum()加Q_INVOKABLE;2. 检查QML中函数名是否与C++一致 |
| 程序闪退,提示"Could not load qrc:/main.qml" | 1. qml.qrc没添加main.qml;2. 路径写错(比如写成"main.qml"而非"qrc:/main.qml") | 1. 打开qml.qrc,确认main.qml已添加;2. 检查url是否为qrc:/main.qml |
| 编译报错"undefined reference to vtable for BackendClass" | 1. 没加Q_OBJECT宏;2. 没有重新运行qmake(MOC没生成代码) | 1. 添加Q_OBJECT宏;2. 右键项目 → 运行qmake → 重新编译 |
| QML调用C++函数无响应,但无报错 | C++函数抛出异常,或QML没触发调用 | 1. 在C++函数中加qDebug()日志,确认是否被调用;2. 检查QML的onClicked是否绑定正确 |
六、扩展知识点(进阶方向)
1. C++信号通知QML更新界面
在backendclass.h中添加信号和属性:
cpp
Q_PROPERTY(int num READ getnum WRITE setnum NOTIFY numChanged) // 属性绑定
private:
int m_num = 42;
public slots: // 槽函数:可被QML调用,也可连接信号
void setnum(int newNum) {
if (m_num != newNum) {
m_num = newNum;
emit numChanged(m_num); // 发送信号,通知QML更新
}
}
signals:
void numChanged(int newNum);
QML中绑定属性(自动更新):
qml
Text{
text: myBackend.num // 绑定属性,C++发送numChanged后自动更新
}
Button{
text: "修改数值为100"
onClicked: myBackend.setnum(100) // 调用槽函数修改数值
}
2. 上下文属性(全局单例)
如果只需一个BackendClass实例,可改用上下文属性(无需qmlRegisterType):
cpp
// main.cpp中替换registerClass()
BackendClass backendObj;
engine.rootContext()->setContextProperty("backendObj", &backendObj);
QML中直接调用(无需实例化):
qml
Text{
text: backendObj.getnum()
}
七、总结(核心知识点回顾)
- 基础前提 :C++类必须继承
QObject+加Q_OBJECT宏,才能被QML识别; - 注册类核心 :
qmlRegisterType需在load QML前调用,QML中import对应命名空间后可实例化; - 函数调用 :C++函数加
Q_INVOKABLE标记,QML通过实例id+函数名调用; - 工程配置 :pro文件需添加
QT += qml quick controls2,QML文件必须加入资源文件; - 调试技巧 :在C++函数中加
qDebug()日志,验证是否被QML调用。