当前位置: 首页 > news >正文

QML学习笔记(四十三)QML与C++交互:上下文属性暴露

前言

在之前的学习中,我们已经对qml的基本组件和布局方式有了大概的了解,已经具备开发一个完善界面的基本能力。然而光会写界面是远远不够的,我们还需要让QML界面和业务代码连接起来也就是说,我们需要学会——QML和C++之间的交互。
之前的学习已经介绍过,QML更偏向于UI界面层,而C++应当负责复杂的业务逻辑判断。
本节我们将学习在QML端如何链接调用到C++对象的函数接口。我利用的是之前的一个qml例子,里面实现了一个登录窗口,上面可以输入用户名和密码,我希望在点击登录后,将用户名密码传递到C++端进行一些业务逻辑,然后返回到QML端。
用到的方法是上下文属性暴露,你可能对此有些迷茫,实际上这是接口名字的翻译。setContextProperty——设置上下文属性。

一、C++端

先贴上登录类的C++头文件代码:

#pragma once
#include <QMainWindow>
#include <QQuickWidget>class QmlLogin : public QMainWindow {Q_OBJECTpublic:QmlLogin(QWidget* parent = nullptr);~QmlLogin();// 可被QML调用的接口Q_INVOKABLE void regularMethod();Q_INVOKABLE QString regularMethodWithReturn(QString name, int age);public slots:void handleLogin(const QString& username, const QString& password);private:QQuickWidget* m_quickWidget;  // 保存QQuickWidget指针
};

我这里打算直接new一个QQuickWidget,然后在构造函数中加载qml。这一点是区别于纯qml工程的。这里设计了三个接口,都可以被qml端调用。
1.regularMethod和regularMethodWithReturn是public的一个公共接口,这里必须要添加Q_INVOKABLE宏 ,代表接口可被调用的意思,否则qml端无法识别调用。
2.槽函数handleLogin可以直接被调用
然后,我再附上cpp代码:

#include "QmlLogin.h"
#include <QQmlContext>
#include <QQuickWidget>
#include <QDebug>
#include <QQmlError>
#include <QQuickItem>
#include <QQuickView>
#include <QQmlProperty>QmlLogin::QmlLogin(QWidget* parent): QMainWindow(parent)
{m_quickWidget = new QQuickWidget(this);// 添加调试信息qDebug() << "Loading QML file...";QUrl qmlUrl("qrc:/LoginWidget.qml");qDebug() << "QML URL:" << qmlUrl.toString();// 将QmlLogin实例暴露给QML上下文m_quickWidget->rootContext()->setContextProperty("loginHandler", this);m_quickWidget->setSource(qmlUrl);// 检查是否有错误if (m_quickWidget->status() == QQuickWidget::Error) {for (const QQmlError &error : m_quickWidget->errors()) {qDebug() << "QML Error:" << error.toString();}}m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);setCentralWidget(m_quickWidget);resize(400, 300);m_quickWidget->show();
}QmlLogin::~QmlLogin()
{
}void QmlLogin::handleLogin(const QString& username, const QString& password)
{qDebug() << "登录请求 - 用户名:" << username << "密码:" << password;// 这里添加您的登录业务逻辑
}
void QmlLogin::regularMethod()
{qDebug()<<"regularMethod";
}QString QmlLogin::regularMethodWithReturn(QString name, int age)
{qDebug()<<"regularMethodWithReturn"<<name<<age;return QString("%1: %2years old").arg(name).arg(age);
}

代码比较简单,这里重点讲:

m_quickWidget->rootContext()->setContextProperty("loginHandler", this);

设置上下文属性——这里将this指针作为一个属性,暴露给了qml引擎,并取了别名loginHandler。之后qml端就可以像调用对象一样调用loginHandler的接口了。
值得一提的事,这里虽然是通过QQuickWidget来调用rootContext的,但实际上链接到的是QQuickWidget里的engine里的rootContext。如果你是在main中直接通过QQmlEngine加载qml的,那调用QQmlEngine的rootContext就行了。
只要 C++ 对象通过 setContextProperty(“name”, obj) 注册到 同一个 QQmlEngine,所有由该引擎加载的 QML 文件(无论多少个窗口/组件)全局共享这个 “name” ——不需要重新 import、不需要重新创建实例,直接写对象名即可访问其属性/信号/槽。
一个引擎,一次注册,处处可用。

二、QML端

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12Rectangle {x: 0y: 0width: 400height: 300color: "#fff0f0"Column {anchors.centerIn: parentspacing: 20Text {text: "登录"font.pixelSize: 24anchors.horizontalCenter: parent.horizontalCenter}TextField {id: usernameFieldplaceholderText: "用户名"width: 200}TextField {id: passwordFieldplaceholderText: "密码"echoMode: TextInput.Passwordwidth: 200}Button {text: "登录"anchors.horizontalCenter: parent.horizontalCenterwidth: 100onClicked: {console.log("登录按钮被点击")loginHandler.handleLogin(usernameField.text, passwordField.text)}}Button {text: "测试"anchors.horizontalCenter: parent.horizontalCenterwidth: 100onClicked: {console.log("测试按钮被点击")loginHandler.regularMethod()var string = loginHandler.regularMethodWithReturn("Jame", 20)console.log(string)}}}
} 

这是一个相当简洁的登录窗口,我们点击登录按钮后,会直接调用暴露的对象属性,然后产生c++端的打印。

loginHandler.handleLogin(usernameField.text, passwordField.text)

在这里插入图片描述
接下来如果需要网络上的请求校验的话,就可以直接在c++端去执行了。
接下来看测试按钮,这个按钮和登录功能无关,纯粹是为了测试添加了Q_INVOKABLE宏的接口能否被调用:
在这里插入图片描述
可以看到,点击测试按钮后,从qml到c++,再到qml获取到返回值进行打印,整个流程都是通畅的。这个返回值是一个简单的字符串拼接,模拟了在c++端进行复杂业务逻辑计算后,将结果返回到qml端进行显示。

三、总结

本节介绍了通过上下文属性暴露的方法,让qml端可以直接通过c++对象的属性,调用它的一些功能接口,属于是qml对c++的单向调用。
下一节,将介绍一下c++端对qml端的主动调用,然后去获取qml界面中一些组件的属性信息。

http://www.dtcms.com/a/498800.html

相关文章:

  • Redis 的字符串底层实现
  • 递归-206.反转链表-力扣(LeetCode)
  • 【Linux系列】掌控 Linux 的脉搏:深入理解进程控制
  • 百度怎么注册公司网站wordpress 2019主题谷歌字体
  • 算法14.0
  • 基于掌纹生物特征的 Windows 安全登录实践:从物理安全到零信任身份验证
  • uniapp map地图添加浮层
  • 可靠的tcp连接
  • 【uniapp】uni.uploadFile上传数据多出一个304的get请求处理方法
  • uni-app 入门学习教程,从入门到精通,uni-app组件 —— 知识点详解与实战案例(4)
  • 购物网站开发实例wordpress flash加载插件
  • 音视频ffmpeg
  • MySQL: 高并发电商场景下的数据库架构演进与性能优化实践
  • 微网站建设是什么推荐做问卷的网站
  • [SCADE编译原理] 初始化分析原理(2004)
  • VB.NET2003和VB2008可以导入VB6项目
  • 反常积分的判敛散
  • SCP2025T2:P14254 分割(divide) 题解
  • LeetCode 3397. 执行操作后不同元素的最大数量
  • 零基础学AI大模型之RAG系统链路解析与Document Loaders多案例实战
  • 北京房产网站大全怎么查找关键词排名
  • 2025年--Lc201- 378. 有序矩阵中第 K 小的元素(排序)--Java版
  • 基于2015年背景下的长虹集团数字化转型案例分析-市场背景资料搜集与整理
  • eduAi-智能体创意平台
  • OpenCV编程入门:从零开始的计算机视觉之旅
  • 肇庆网站制作策划麦包包的网站建设
  • 分享一个基于微信小程序的个性化服装搭配推荐平台设计与实现,利用uniapp框架开发的跨平台女装穿搭小程序,源码、调试、答疑、lw、开题报告、ppt
  • 网站建设方案服务公司网站整体色调
  • 如何将喜欢的哔哩哔哩视频保存起来
  • 【OpenHarmony】HDF 核心框架