文章目录

  • 1. QWebChannel
  • 2. 使用QWebEngine的示例
    • 2.1 C++端代码
      • 2.1.1 mainwindow.cpp
      • 2.1.2 mytestclass.h
      • 2.1.3 mytestclass.cpp
    • 2.2 Web端
    • 2.3 运行
  • 3. 使用WebSocket的示例
    • 3.1 C++端代码
      • 3.1.1 mainwindow.cpp
    • 3.2 Web端代码
    • 3.3 运行
    • 3.4 问题
  • 4. 代码

1. QWebChannel

QWebChannel类的作用是向远端HTML客户端暴露 QObject。

QWebChannel填补了C++应用程序和HTML/JavaScript 应用程序之间的空白。通过将QObject派生对象发布到QWebChannel并在HTML中引入qwebchannel.js脚本可从此处获取。在HTML端,可以透明地访问QObject的属性、公共槽和方法。不需要手动消息传递和数据序列化,C++方面的属性更新和信号发射将自动传输到可能远程运行的HTML客户机。在客户端,将为任何发布的C++ QObject创建JavaScript对象。它反映了C++对象的API,因此可以直观地使用。

但是,Web端与C++之间怎么进行通信能? 有两个方法:

  • QWebEngine 提供一个 web 引擎,用于在 Qt 应用中嵌入任意的网页内容。Qt WebEngine 是基于 Chromium 项目实现的,提供了一个 js 的宿主环境,内部实现了js调用C++的环境;
  • Websocket C++端建立websocket server,Web端连接,qwebchannel.js会获取到C++端所有的属性、槽函数等。

2. 使用QWebEngine的示例

2.1 C++端代码

2.1.1 mainwindow.cpp

// 要导出的类,此类供js调用
m_myTestClass = new MyTestClass(this);// 创建QWebChannel,把创建的类注册到QWebChannel中,js才能调用此类的方法
m_webChannel = new QWebChannel(this);
m_webChannel->registerObject("mytestclass", m_myTestClass);// js与C++通信方式一、使用QWebEngineView加载网页,web端js与C++之间的通信
QString strHtml = QApplication::applicationDirPath() + "/../../testWeb/test.html";
// QWebEngineView 基于 Chromium 的 web 引擎
m_webEngineView = new QWebEngineView(this);
m_webEngineView->load(QUrl::fromLocalFile(strHtml));
m_webEngineView->page()->setWebChannel(m_webChannel);
ui->verticalLayout->addWidget(m_webEngineView);

导出类 MyTestClass,供js调用

2.1.2 mytestclass.h

#ifndef MYTESTCLASS_H
#define MYTESTCLASS_H#include <QObject>
#include <QThread>class MyTestClass : public QObject
{Q_OBJECT// 导出的属性Q_PROPERTY(QString navStatus MEMBER m_navStatus NOTIFY navStatusChanged)public:explicit MyTestClass(QObject *parent = nullptr);signals:// 导出的事件void navStatusChanged(const QString& navStatus);public slots:// 导出的槽函数void function1(const QString& str);private:void setNavStatus(const QString& status);QString m_navStatus;};#endif // MYTESTCLASS_H

2.1.3 mytestclass.cpp

#include "mytestclass.h"#include <QMessageBox>
#include <QVariant>
#include <QDebug>MyTestClass::MyTestClass(QObject *parent) : QObject(parent),m_navStatus("hello")
{}void MyTestClass::function1(const QString& str)
{setNavStatus(str);qDebug() << __FUNCTION__ << str;
}void MyTestClass::setNavStatus(const QString &status)
{m_navStatus = status;emit navStatusChanged(m_navStatus);
}

2.2 Web端

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="callcpp" onclick="callcpp()">callcpp</button><button onclick="getValue()">getValue</button><script src="qwebchannel.js"></script><script type="text/javascript">var webObj;// 创建Webchannel,与C++端建立连接new QWebChannel(qt.webChannelTransport, function (channel) {// 获取类的对象webObj = channel.objects.mytestclass;// 类的事件webObj.navStatusChanged.connect(function(arg){alert("navStatusChanged: " + arg);});});function callcpp(){// 类的方法webObj.function1('this is a test');}function getValue(){// 类的属性值var status = webObj.navStatus;alert(status);}</script>
</body>
</html>

其中,qwebchannel.js 取自 Qt安装目录的 Qt5.12.0\Examples\Qt-5.12.0\webchannel\shared 目录。

2.3 运行


QT UI加载了html页面,显示了其中的元素。

(1)Web端的getValue获取C++对象的属性navStatus,属性初始值为 “hello”
           
(2)Web端的 callcpp 调用 C++端的函数 function1,C++端function1函数中打出
           
(3)Web端响应 navStatusChanged 事件


3. 使用WebSocket的示例

3.1 C++端代码

3.1.1 mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);// 要导出的类,此类供js调用m_myTestClass = new MyTestClass(this);// 创建QWebChannel,把创建的类注册到QWebChannel中,js才能调用此类的方法m_webChannel = new QWebChannel(this);m_webChannel->registerObject("mytestclass", m_myTestClass);// js与C++通信方式二、创建QWebsocketServer,web端与之建立连接startServer();}MainWindow::~MainWindow()
{delete ui;
}// 建立WebSocket服务
void MainWindow::startServer()
{m_websocketServer = new QWebSocketServer("testWebchannel", QWebSocketServer::NonSecureMode, this);if(!m_websocketServer->listen(QHostAddress::Any, 12345)){qDebug() << "websocket server listen failed, error: " << m_websocketServer->errorString();return;}connect(m_websocketServer, &QWebSocketServer::newConnection, this, &MainWindow::onNewConnection);qDebug() << "startServer";
}void MainWindow::onNewConnection()
{QWebSocket* client = m_websocketServer->nextPendingConnection();qDebug() << (QString("Homay robot server has new connection from %1.%2").arg(client->peerAddress().toString()).arg(client->localPort()));auto pTransport = new WebSocketTransport(client);// 可以不需要,这里只是为了调试打印js端的qwebchannel.js是怎么和C++端通信的,通信协议是什么样的connect(pTransport, &WebSocketTransport::messageReceived, this, &MainWindow::onTransportMessageReceived);m_webChannel->connectTo(pTransport);
}void MainWindow::onTransportMessageReceived(const QJsonObject &message, QWebChannelAbstractTransport *transport)
{qDebug() << "onTransportMessageReceived: " << message;
}

导出类 MyTestClass,供js调用。
代码中 WebSocketTransport 类代码,取自 Qt安装目录的 Qt5.12.0\Examples\Qt-5.12.0\webchannel\shared 目录下的 websockettransport.h websockettransport.cpp
此处省略。

3.2 Web端代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="callcpp" onclick="callcpp()">callcpp</button><button onclick="getValue()">getValue</button><script src="qwebchannel.js"></script><script type="text/javascript">var webObj;// 连接c++端的 Websocketvar socket = new WebSocket('ws://127.0.0.1:12345');// 连接成功后socket.onopen = function(){alert("onopen");// 创建Webchannelnew QWebChannel(socket, function (channel) {// 获取类的对象webObj = channel.objects.mytestclass;// 类的事件webObj.navStatusChanged.connect(function(arg){alert("navStatusChanged: " + arg);});});}function callcpp(){// 类的方法webObj.function1('this is a test');}function getValue(){// 类的属性值var status = webObj.navStatus;alert(status);}</script>
</body>
</html>

与2.2中的Web端代码相比,此时,需要先创建WebSocket连接,把socket传入QWebChannel中。

3.3 运行

(1)运行C++, C++代码没有加载html, 此时为空界面;
(2)使用Chrome浏览器,或者Edge浏览器打开Web测试网页,一打开就与C++端的websocket连接上了
           
(3)接下来与2.3的演示一样。

3.4 问题

我这里端口用的12345,可能在有些电脑上此端口被占用了,会报错:

改一下端口号就好了, 比如我改成:

4. 代码

所有代码详见:QWebChannel

Qt QWebChannel web端js与C++交互相关推荐

  1. Emqx3.4.4(企业版试用) web端 js实现消息的发布接收

    本文只介绍如何进行消息的发布,接收,至于emqx服务器需要靠 小伙伴们自己 本文章emq服务器为企业版试用,但消息的接收发布与emqx broker是一样的 Paho.mqtt.js Paho 是 E ...

  2. Web 端 js 导出csv文件(使用a标签)

    前言 导出文件,使用最多的方式还是服务器端来处理.比如jsp 中使用response 的方式. 但是,有时候可能就想使用web 前端是否也可以把页面上的内容导出来呢? 比如说,导出页面的一个表格. 这 ...

  3. 高德地图 web 端 JS API 遇到的坑及性能优化

    [JS API V2.0] 本指望全面提升一下性能,结果发现一些硬伤,迫不得已转到1.4.15版本,先说一下最新的v2.0的问题. 因为务业需要规划线路,但是这个版本中,规划线路,并且经过中间点时,部 ...

  4. vue使用高德地图web端JS API(vue-amap插件)

    高德地图地图 JS API v2.0:https://lbs.amap.com/api/jsapi-v2/summary/ vue-amap(基于Vue 2.0和高德地图的地图组件):https:// ...

  5. web 端JS取得window 的按键动作(按下Shift, Alt,Ctrl....)

    如何取得 基本上都是从动作的event 中去判断. IE下的处理 在IE中, window 对象里就有包含event. 看例子: <!--Add by oscar999--> <!D ...

  6. 高德地图web端js

    下面是一些高德地图使用例子,自定义展示,右击拖动,搜索,画圆,定位等功能,没有整理仅供参考 var infoWindow = new AMap.InfoWindow({isCustom:true,// ...

  7. 论文研读-图可视化-NetV.js:Web端可视化工具库

    NetV.js:一个基于网络的用于大规模图和网络的高效可视化的库 1 论文概述 1.1 文章摘要 1.2 引言 1.3 文章脉络 2 相关工作 3 设计 3.1 设计要求 3.2 设计细节 3.2.1 ...

  8. WEB端Monkey测试gremlins.js

    一直想做web端UI自动化测试,网上查阅了 大量的资料,发现有一个线程的monkey测试工具,地址:https://github.com/marmelab/gremlins.js.但是我对js不是很精 ...

  9. web电商系统、电商平台WEB端交互原型模板、用户中心、会员中心、优惠券、积分、互动社区、运营推广、内容推荐、商品展示、订单流程、订单管理、售后及服务、Axure原型、rp原型、电商原型、商城系统原型

    作品介绍:web电商系统.电商平台WEB端交互原型模板.用户中心.会员中心.优惠券.积分.互动社区.运营推广.内容推荐.商品展示.订单流程.订单管理.售后及服务等完整的电商体系功能架构和业务流程 Ax ...

最新文章

  1. Ajax跨域请求action方法,无法传递及接收cookie信息(应用于系统登录认证及退出)解决方案
  2. python断点续传下载_Python版本,图片,视频断点续传下载
  3. qt 判断ctrl键被按下_惊雷!证监会公告,又一家千亿白马股被按下“暂停键”...
  4. 九十九、Python所学经验分享
  5. C#设计模式(5)-Factory Method Pattern
  6. php提交表单显示错误,php – 在提交注册表单时使用jQuery显示错误
  7. 每个人都应该使用的Python 3中被忽略的3个功能
  8. 前端学习(1081):构造函数和原型概述
  9. 2019牛客暑期多校训练营(第三场) B-Crazy Binary String
  10. 屏幕的宽度_交互规范:响应式让屏幕利用更高,用户体验更佳
  11. 40个非常有创意的国外LOGO欣赏(上)
  12. Imagej分析所有气泡的粒径
  13. 【优化求解】基于matlab改进的遗传算法求解带约束的优化问题【含Matlab源码 1773期】
  14. SoftCnKiller高速下载器捆绑软件杀手
  15. Selpg—Golang
  16. ubuntu系统启动项的修改
  17. CSS实现优惠券特殊样式的技巧
  18. [深度学习] (sklearn)多层感知机对葡萄酒的分类
  19. 你要找到黑夜里代替阳光的东西,那个叫做信念
  20. [原创].NET中防止Access数据库下载

热门文章

  1. python视频搬运_Python-自动下载抖音无水印高清视频
  2. 【PTA】 7-3 玩转二叉树 (二叉树静态建树+左右子树交换+层次遍历)
  3. 有了中值联区块链证书我们对钓鱼网站说“不”
  4. 计算机会计中出纳的职责有哪些,作为一名学校出纳工作职责有哪些
  5. modbus/施耐德PLC协议网关
  6. 【Android】Android设备唯一标识简介
  7. Specify @BootstrapWith's 'value' attribute or make the default bootstrapper class available.
  8. 商业世界的交易结构到底有哪些?
  9. 深度学习论文精读[10]:Deeplab v1
  10. 达梦数据库基础知识(十一)管理分区表和分区索引