详解如何在 QML 中调用 C++ 中的内容
在 Qt 开发中,经常需要在 QML 界面中访问 C++ 定义的逻辑或数据。核心方法是使用 QQmlContext 的 setContextProperty 将 C++ 对象或值注入引擎上下文。本文将基于 Qt5.12 环境,演示如何传递基本数据类型以及如何通过 QObject 派生类、Q_INVOKABLE 方法和信号槽机制实现 QML 对 C++ 功能的动态调用。
环境与前置条件
本教程基于以下环境进行验证:
- 操作系统/IDE:Windows (Visual Studio 2017) x64
- 框架版本:Qt 5.12
核心 API 为 QQmlContext::setContextProperty,它支持两种赋值方式:设置基本兼容类型或设置 QObject* 指针。前者仅用于静态数据显示,后者可用于触发 C++ 逻辑和响应信号。
第1步:在 QML 中引用 C++ 基本类型数据
如果仅需在 QML 中显示固定的 C++ 变量值,可以直接将该变量添加到引擎上下文中。
操作入口:C++ 应用程序入口文件(如 main.cpp)。
具体动作:
- 创建
QQmlEngine实例。 - 准备需要共享的数据对象(如
QDateTime)。 - 调用
engine.rootContext()->setContextProperty("name", &value)将其注册到全局上下文。
// main.cpp
#include <QDateTime>
#include <QQmlEngine>
void main() {
// ... 其他初始化代码 ...
QQmlEngine engine;
// 1. 获取当前时间
QDateTime dateTime = QDateTime::currentDateTime();
// 2. 将变量名 "dateTime" 绑定到 cpp 变量地址
engine.rootContext()->setContextProperty("dateTime", &dateTime);
// ... 加载 QML 文件 ...
}
在 QML 中使用:
Rectangle {
id: window
Text {
// 直接引用名称 "dateTime"
text: dateTime.toString()
}
}
注意:这种方式获取的是快照数据。如果在 C++ 后续修改了变量值,QML 端不会自动刷新,因为它没有建立对象间的信号连接。
第2步:在 QML 中调用 C++ 对象方法与属性
若需在 QML 中触发 C++ 逻辑(如计算、网络请求)并实时更新界面,需创建一个继承自 QObject 的类,并将其实例指针注入上下文。
1. 定义 C++ 数据类
创建派生自 QObject 的类,必须包含 Q_OBJECT 宏。对于需要在 QML 调用的方法,需标记 Q_INVOKABLE;对于需要通知 QML 变化的数据变动,需定义 signals 和 slots。
// applicationdata.h
#ifndef APPLICATIONDATA_H
#define APPLICATIONDATA_H
#include <QObject>
#include <QDateTime>
#include <QTimer>
class ApplicationData : public QObject
{
Q_OBJECT
public:
explicit ApplicationData(QObject *parent = nullptr) : QObject(parent) {
// 启动定时器模拟数据源更新
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &ApplicationData::slt_timeout);
timer->start(1000); // 每秒更新一次
}
// 声明该方法可被元对象系统调用(QML 可见)
Q_INVOKABLE QDateTime getCurrentDateTime() const {
return m_currentDateTime;
}
signals:
void sig_dataTimeUpdated();
private slots:
void slt_timeout() {
m_currentDateTime = QDateTime::currentDateTime();
emit sig_dataTimeUpdated(); // 发射信号通知 QML
}
private:
QDateTime m_currentDateTime;
};
#endif // APPLICATIONDATA_H
2. 将对象指针注入引擎
在 main.cpp 中实例化该类,并将其指针设置给上下文。
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "applicationdata.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// 实例化 C++ 业务对象
ApplicationData data;
// 将实例指针以名字 "currentDateTime" 暴露给 QML
engine.rootContext()->setContextProperty("currentDateTime", &data);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
3. 在 QML 中接收信号并调用方法
使用 Connections 元素监听 C++ 对象的信号。当信号触发时,调用之前在 C++ 中标记为 Q_INVOKABLE 的方法获取最新数据。
// main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
id: window
visible: true
width: 640
height: 480
title: qsTr("QML Call C++ Demo")
Text {
id: name_id
anchors.centerIn: parent
font.pixelSize: 24
}
// 连接到 C++ 对象 "currentDateTime"
Connections {
target: currentDateTime
// 响应 C++ 发出的信号
onSig_dataTimeUpdated: {
// 调用 C++ 的 Q_INVOKABLE 方法获取实时数据
name_id.text = currentDateTime.getCurrentDateTime().toString();
}
}
}
通过上述配置,QML 界面将每秒动态刷新由 C++ 后端产生的时间数据。这种模式避免了 UI 线程阻塞,同时实现了前后端逻辑的解耦。
以上就是通过 setContextProperty 实现 QML 调用 C++ 内容的详细内容。这种方法适用于从简单的参数传递到复杂的服务层交互。更多关于 Qt QML 与 C++ 混合编程的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









