Qtl和JS、HTML通信/交互
http://www.cnblogs.com/sigma0/p/7346727.html
Qt的QWebChannel和JS、HTML通信/交互驱动百度地图
0 前言
我一个研究嵌入式的,不知道怎么就迷上了上位机,接了几个项目都是关于Qt,这个项目还是比较经典的,自己没事儿的时候也进行研究,对这个软件进行升级,反正,我喜欢编程,喜欢研究这些东西。研究了一下午,查了很多资料,看了很多的例子,我对于JS是0基础,能稍微看懂一点点HTML语言的东西,下午调试了好几遍,运行了好几遍,终于在我更改了JavaScript的函数完毕之后,一下子数据回传成功了,那种感觉很棒!!!特地写这个博客,记录我的研发成果。
- 我是一个业余研究Qt的,不是那么专业! *
【正文】
QWebChannel官方给的例子是和Socket混合,看的是一头雾水,不得不吐槽Qt了,能不能单独讲讲使用方法,别和别的东西结合?!
对于我的GPS地图项目,研究又有了新的进展,我在本年度一直在业余时间研究Qt开发的软件和网页交互(JS和HTML),虽然我对于网页的知识仅仅有个基础,在业余方面,我也不断的在对该软件进行升级研究,目前状态:
- 第一阶段:在Qt5.6以下版本,Qt还没有删除QWebKits组件,基于QWebKits组件,我做了最基本的软件:参考:Qt开发北斗定位系统融合百度地图API及Qt程序打包发布,
- 第二阶段:Qt5.6以上版本,删除了QWebKits组件,升级为QWebEngine组件,但是过渡阶段只能由Qt的C++程序去运行JS,JS反馈的数据无法回传,这造成了我获取当前鼠标经纬度的功能缺失。参考:QtWebkits如何向QtWebEngine过渡。
- 第三阶段:基于第二个阶段,依旧基于QWebEngine,引入QWebChannel通信机制,完成JavaScript给的回传数据,还原了鼠标当前经纬度的获取功能。
到目前为止,GPS定位系统交互驱动百度地图已经完全适配QWebEngine组件。
如图1:
红色方框部分为当前鼠标的经纬度信息,这个信息来源于html访问百度地图的JavaScript,然后回传给C++的信息。
本文重点来说一下,如何从JavaScript获取回传信息,实现交互
1 实现过程
1.1 原理阐述
我是非专业的,我也没有找关于HTML和JS交互的书,在我研究的过程中我认为是一个这样的关系:

QWebEngine提供了调用HTML里面JavaScript的方法,这里HTML像是一个接口,在HTML尾部有一个这样的标签, ,在这个标签内的函数和变量体中写入一些函数和变量,这些函数和变量要么是JavaScript中的调用,要么是Qt中的调用,所以,HTML像是一个QT和网页的桥梁。在下面的章节,我们详细讨论一下步骤。
1.2 WebChannel的使用
要使用QWebChannel要打点好两个方面,第一,Qt方面,需要包含QWebChannel类,注册好QWebChannel需要连接的Qt的对象;第二,JS方面,官方提供了配套的qwebchannel.js文件,这个js文件就相当于驻JavaScript负责通信的。所需准备的:
- 【JS方面:】qwebchannel.js文件(Qt官方提供,需要在html中引入,拿到后里面什么代码都不要修改,直接使用。) qwebchannel.js下载地址
- 【Qt方面:】在Qt的主程序中,创建好QWebChannel类
下面就这两方面讨论如何使用:
1.2.1 JS方面处理
地图这块仅有一个JavaScript文件,是驱动百度地图的,但是为了让QWebChannel和百度的JS顺利通信,Qt提供了一个qwebchannel.js文件,这个文件就是负责打点Qt和JS通信用的。
参考源码:我把qwebchannel.js放在和百度地图提供的js(也就是你要通信的JS)放在了一个目录,然后在HTML文件中要引入两个js文件。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>地图演示</title>
<script src="js/qwebchannel.js"></script> <!--> !!!!!!重点1<-->
<script src="js/apiv1.3.min.js"></script>
<!--script type="text/javascript" src="http://api.map.baidu.com/api?v=1.3"></script-->
<link rel="stylesheet" type="text/css" href="bmap.css"/>
</head>
<body>
<div style="left:0;top:0;width:100%;height:100%;position:absolute;" id="container"></div>
</body>
</html>
<script>
var mapOptions={
minZoom: 3,
maxZoom:19,
mapType: BMAP_NORMAL_MAP
}
var map = new BMap.Map("container",mapOptions); // 设置街道图为底图
var point = new BMap.Point(116.468278, 39.922965); // 创建点坐标
map.centerAndZoom(point,14); // 初始化地图,设置中心点坐标和地图级别。
map.addControl(new BMap.NavigationControl({offset: new BMap.Size(10, 90)}));
map.enableScrollWheelZoom(); // 启用滚轮放大缩小。
map.enableKeyboard(); // 启用键盘操作。
map.enableContinuousZoom(); // 启用连续缩放
var myIcon = new BMap.Icon("images/Point.png", new BMap.Size(20,25));
var marker = new BMap.Marker(point,{icon:myIcon}); // 创建标注
map.addOverlay(marker); // 加载标注
// !!!!重点2!!!
new QWebChannel(qt.webChannelTransport,
function(channel){
window.bridge = channel.objects.person; // 注册
}
);
var dragFlag=false;
// !!!!重点3!!!
var updateInfo = function(lng,lat)
{window.bridge.getCoordinates(lng,lat);}functionshowAddress(longjitude,latitude)
{var gpsPoint =newBMap.Point(longjitude, latitude);if(!dragFlag)
{map.panTo(gpsPoint);}marker.setPosition(gpsPoint);}functionshowStreetMap()
{map.setMapType(BMAP_NORMAL_MAP);};functionshowSatelliteMap()
{map.setMapType(BMAP_SATELLITE_MAP);}// !!!!!重点4!!!map.addEventListener("mousemove",function(e) {updateInfo(e.point.lng,e.point.lat);});map.addEventListener("dragstart",function(e){
dragFlag=true;});map.addEventListener("dragend",function(e){
dragFlag=false;});map.addEventListener("zoomend",function(e){});</script>
这么多代码,看的你很焦躁,不用太细研究,里面只是定义了很多百度地图读取的方法,我们把重点放在几个点上(你可以在上面的源码注释中找到重点标记)
- 【第1步】:
<script src="js/qwebchannel.js"></script> <script src="js/apiv1.3.min.js"></script>,这两个语句表示这个HTML负责驱动两个js文件,一个是百度地图的js文件,一个是qwebchannel的js文件,qwebchannel毋庸置疑就是负责交互数据的了,所以在你拿到百度地图原版的HTML文件的时候,需要对这里进行改进,原理貌似就像是C语言中#include这块,把qwebchannel.js集成进来。 - 【第2步】:需要在JS这块创建一个QWebChannel,这个js里的webchannel就是负责和Qt C++里面的webchannel通信的。
// !!!!重点2!!!
new QWebChannel(qt.webChannelTransport, // 新建一个QWebChannel实例化
function(channel){
window.bridge = channel.objects.person; // 注册 // window.bridge不用找了,这个是js的功能函数,等号后边需要注意,channel.objects.XXXXX
} // 这个XXXX是需要在Qt C++程序里面定义的,我们一会儿说,但是channel.objects.这个是固有的。
);
这部分是新添加的,我查了QWebChannel这个东西在qwebchannel.js文件中定义了,这里在我们要访问的HTML中必须要有这个东西的定义,解释详见注释。person这个东西就是在C++里面定义的,就当是他是负责和我们C++和js通信的句柄吧。将他赋值给window.bridge,以后利用操作window.bridge我们就可以通信了。
- 【第3步】:利用channel这个东西通信。
// !!!!重点3!!!
var updateInfo = function(lng,lat)
{
window.bridge.getCoordinates(lng,lat);
}
这里定义一个函数,就是将lng和lat这两个参数传递给Qt C++,通过这样的方式就能回传数据了。window.bridge说过了是固有的,js固有的,那么getCoordinates这个东西是什么?答曰,是我们Qt C++里面自定义的一个槽函数,声明在public slots:里面,channel通过window.bridget来操控槽函数,达到数据回传,这个地方是重中之重!!
- 【第4步】:配合监听器,这里有个注意点。
// !!!!!重点4!!!
map.addEventListener("mousemove",function(e) {
updateInfo(e.point.lng,e.point.lat);
});
当发生mousemove这个行为的时候,这可能是JS里面的知识,则调用function(e),一定要注意这个function不能直接把函数体写在这里,必须采用我们上面的方法,把函数体单独写,然后在内部写上调用。
到此javascript部分已经交代清楚了。
1.2.2 Qt C++方面处理
Qt C++方面的开发,需要启动QWebChannel类,注册页面。
// 准备Javascript文件交互
QString strMapPath = "qrc:/map/map.html"; // 设定地图路径
QWebEnginePage *page = new QWebEnginePage(this); // 定义QWebEnginePage界面负责打开html文件
QWebChannel *channel = new QWebChannel(this); // 定义QWebChannel负责
channel->registerObject(QString("person"),this); // QWebChannel对Widget类,注册一个person的通信介质 /
// 在js文件中person负责成为window.bridge /
// 在this中也就是Widget类注册channel,channel访问的位Widget下的槽函数。
page->load(strMapPath); // webenginePage加载html地图。
page->setWebChannel(channel); // webenginePage加载Channel功能
ui->webEngine->setPage(page); // ui显示该page。
在C++类Widget的构造函数,要进行准备,这里涉及了QWebEnginePage,QWebChannel,千万别乱,按照代码注释里清楚关系。这里有个QString类,定义了person,在返回去看js中的person,是不是明白了其中的联系了?!你可以写成任意可理解的字符。
紧接着就是槽函数了:必须是public slots: 不能是private slots
public slots:
void getCoordinates(QString lon, QString lat) {
QString tempLon="Mouse Lontitude:"+lon+"°";
QString tempLat="Mouse Lattitude:"+lat+"°";
ui->label_mouse_altitude->setText(tempLat);
ui->label_mouse_latitude->setText(tempLon);
};
经过以上,js会回传数据给lon和lat,然后你该怎么办就怎么办了。
2 总结
经过一下午的努力,完成了数据回传,可以将js的数据传递回来,但是QWebChannel这块还有其他的东西,比如和槽和信号连接,如果今后能遇到这个项目,我会继续研究,否则,到今天这个项目完毕。
感谢观看。
参考文献:
【木有】
版权声明:
1. 本文为MULTIBEANS团队研发跟随文章,未经允许不得转载。
2· 文中涉及的内容若有侵权行为,请与本人联系,本人会及时删除。
3· 尊重成果,本文将用的参考文献全部给出,向无私的工程师,爱好者致敬。
QT += webenginewidgets
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QWebChannel>
#include <QWebEngineView>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this); testBtn *pBtn = new testBtn;
m_pWebView = new QWebEngineView(this);
m_pWebView->showMaximized();
QWebEnginePage *page = new QWebEnginePage(this);
QWebChannel *pChannel = new QWebChannel(this);
QObject *pobject = pBtn; pChannel->registerObject(QString("person"), pobject);
page->setWebChannel(pChannel);
page->load(QUrl("file:///home/qilin64/Documents/TE.html"));
m_pWebView->setPage(page);
this->showMaximized();
//m_pWebView->show();
} MainWindow::~MainWindow()
{
delete ui;
} #ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow>
#include <QDialog>
#include <QtWebEngineWidgets/QWebEnginePage>
#include <QtWebEngineWidgets/QWebEngineView> class testBtn : public QDialog
{
Q_OBJECT
public slots:
void getCoordinates(QString ss); }; namespace Ui {
class MainWindow;
} class MainWindow : public QMainWindow
{
Q_OBJECT public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QWebEngineView *m_pWebView;
public slots:
void getCoordinates(QString ss);
private:
Ui::MainWindow *ui;
};
<html>
<script language="JavaScript">
function qtcalljs()
{
alert("sdfsd");
}
function jscallqt()
{
alert("call qt object");
content.receiveJs();
}
</script>
<body>
<button onclick="jscallqt()" style=="height:200px;width:1000px"/>
</body>
</html>
Qtl和JS、HTML通信/交互的更多相关文章
- Qt的QWebChannel和JS、HTML通信/交互驱动百度地图
Qt的QWebChannel和JS.HTML通信/交互驱动百度地图 0 前言 我一个研究嵌入式的,不知道怎么就迷上了上位机,接了几个项目都是关于Qt,这个项目还是比较经典的,自己没事儿的时候也进行研究 ...
- JS 与Flex交互:html中的js 与flex中的actionScript通信
Flex与JavaScript交互的问题,这里和大家分享一下,主要包括Flex调用JavaScript中的函数和JavaScript调用Flex中的函数两大部分内容. Flex 与JavaScript ...
- 史上最全的 UIWebview 的 JS 与 OC 交互
来源:伯乐在线 - 键盘风筝 链接:http://ios.jobbole.com/89330/ 点击 → 申请加入伯乐在线专栏作者 其实一直想给大家整理一下JS与OC的交互,但是没有合适的机会,今天借 ...
- WebView全面学习(二)-- Native与js双方通信
WebView全面学习(二)-- Native与js双方通信 Native与js通信的本质 Native与js通信的核心在于WebView. 两端的通信主要还是单向的.假如要完成js->Nati ...
- js与native交互
js与native交互 UIWebView Native调用JS,使用stringByEvaluatingJavaScriptFromString来解释执行js脚本. //script即为要执行的js ...
- CEF3开发者系列之JS与C++交互之一
JS与Native交互是相对于比较困难的技术,在学习这门技术之前,我们先了解下浏览器内核中的JS引擎与chromium内核的V8引擎相关知识.在浏览器应用中,JS与本地代码互相调用,得益于浏览器内核对 ...
- js与C++交互及C++解析json
转载:http://zhidao.baidu.com/link?url=LLuWzwMmpfVcQeSGv1CrAfRXpnZaetm9xypqwMW6zxLhhKES-rITAsG0-Ku-bSMA ...
- OC和JS之间的交互
OC和JS之间的交互 目录 对OC和JS之间交互的理解 JS调用OC OC调用JS 对OC和JS之间交互的理解 JS调用OC JS文件 function sendCommand(cmd,param){ ...
- UIWebView与JS的深度交互
我要实现这样一个需求:按照本地的CSS文件展示一串网络获取的带HTML格式的只有body部分的文本,需要自己拼写完整的 HTML.除此之外,还需要禁用获取的HTML文本中自带的 < img &g ...
随机推荐
- npm 修改源 pip 修改源
npm修改源由于不可说原因,npm install时,速度总是不尽如人意,解决办法是修改npm的数据源npm config set registry https://registry.npm.taob ...
- 洛谷 P2518 [HAOI2010]计数 (组合数)
题面 luogu 题解 本来想练数位dp的,结果又忍不住写了组合数.. 去掉一个\(0\)可以看作把\(0\)移到前面去 那么题目转化为 \(n\)有多少个排列小于\(n\) 强制某一位比\(n\)的 ...
- POJ3322 Bloxorz I 无脑广搜(我死了。。。)
多测不清空,爆零两行泪....我死了QWQ 每个节点3个状态:横坐标,纵坐标,和方向 说一下方向:0:立着,1:竖着躺着,上半部分在(x,y),2:横着躺着,左半部分在(x,y) 然后就有了常量数组: ...
- webApi的控制台服务
1.新建console项目,引用 下面包 2.新建Controller public class UserController : ApiController { public IEnumerable ...
- 设置input placeholder的样式
::-webkit-input-placeholder {/*Chrome/Safari*/ font-family: 'Avenir', Helvetica, Arial, sans-serif; ...
- PHP的魔术常量(变量)、魔术方法(函数)、超全局变量
https://www.cnblogs.com/ccw869476711/p/9183783.html 一.魔术常量(魔术变量) 概念:所谓的魔术常量就是PHP预定义的一些常量,这些常量会随着所在的位 ...
- linux下忘记mysql的root密码
一.处理方案 #1. 结束当前正在运行的mysql进程 /etc/init.d/mysql stop #2. 用mysql安全模式运行并跳过权限验证 mysqld_safe --user=mysql ...
- Caused by java.lang.IllegalStateException Not allowed to start service Intent { cmp=com.x.x.x/.x.x.xService }: app is in background uid UidRecord(一)
Caused by java.lang.IllegalStateException Not allowed to start service Intent { cmp=com.x.x.x/.x.x.x ...
- GreenPlum 大数据平台--并行备份(四)
01,并行备份(gp_dump) 1) GP同时备份Master和所有活动的Segment实例 2) 备份消耗的时间与系统中实例的数量没有关系 3) 在Master主机上备份所有DDL文件和GP相关的 ...
- CDH与原生态hadoop之间的区别(转)
需要认识的几个问题 ------------------------------------------------------------------------------------------ ...