我一个研究嵌入式的,不知道怎么就迷上了上位机,接了几个项目都是关于Qt,这个项目仍是比较经典的,本身没事儿的时候也进行研究,对这个软件进行升级,反正,我喜欢编程,喜欢研究这些东西。研究了一下午,查了不少资料,看了不少的例子,我对于JS是0基础,能稍微看懂一点点HTML语言的东西,下午调试了好几遍,运行了好几遍,终于在我更改了JavaScript的函数完毕以后,一会儿数据回传成功了,那种感受很棒!!!特意写这个博客,记录个人研发成果。javascript
【正文】css
QWebChannel官方给的例子是和Socket混合,看的是一头雾水,不得不吐槽Qt了,能不能单独讲讲使用方法,别和别的东西结合?!html
对于个人GPS地图项目,研究又有了新的进展,我在本年度一直在业余时间研究Qt开发的软件和网页交互(JS和HTML),虽然我对于网页的知识仅仅有个基础,在业余方面,我也不断的在对该软件进行升级研究,目前状态:java
到目前为止,GPS定位系统交互驱动百度地图已经彻底适配QWebEngine组件。c++
如图1:web
红色方框部分为当前鼠标的经纬度信息,这个信息来源于html访问百度地图的JavaScript,而后回传给C++的信息。编程
本文重点来讲一下,如何从JavaScript获取回传信息,实现交互api
我是非专业的,我也没有找关于HTML和JS交互的书,在我研究的过程当中我认为是一个这样的关系:函数
QWebEngine提供了调用HTML里面JavaScript的方法,这里HTML像是一个接口,在HTML尾部有一个这样的标签, ,在这个标签内的函数和变量体中写入一些函数和变量,这些函数和变量要么是JavaScript中的调用,要么是Qt中的调用,因此,HTML像是一个QT和网页的桥梁。在下面的章节,咱们详细讨论一下步骤。ui
要使用QWebChannel要打点好两个方面,第一,Qt方面,须要包含QWebChannel类,注册好QWebChannel须要链接的Qt的对象;第二,JS方面,官方提供了配套的qwebchannel.js文件,这个js文件就至关于驻JavaScript负责通讯的。所需准备的:
下面就这两方面讨论如何使用:
地图这块仅有一个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); } function showAddress(longjitude,latitude) { var gpsPoint = new BMap.Point(longjitude, latitude); if(!dragFlag) { map.panTo(gpsPoint); } marker.setPosition(gpsPoint); } function showStreetMap() { map.setMapType(BMAP_NORMAL_MAP); }; function showSatelliteMap() { 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>
这么多代码,看的你很焦躁,不用太细研究,里面只是定义了不少百度地图读取的方法,咱们把重点放在几个点上(你能够在上面的源码注释中找到重点标记)
<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!!! 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!!! 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!!! map.addEventListener("mousemove",function(e) { updateInfo(e.point.lng,e.point.lat); });
当发生mousemove这个行为的时候,这多是JS里面的知识,则调用function(e),必定要注意这个function不能直接把函数体写在这里,必须采用咱们上面的方法,把函数体单独写,而后在内部写上调用。
到此javascript部分已经交代清楚了。
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,而后你该怎么办就怎么办了。
通过一下午的努力,完成了数据回传,能够将js的数据传递回来,可是QWebChannel这块还有其余的东西,好比和槽和信号链接,若是从此能遇到这个项目,我会继续研究,不然,到今天这个项目完毕。
感谢观看。
【木有】
1. 本文为MULTIBEANS团队研发跟随文章,未经容许不得转载。
2· 文中涉及的内容如有侵权行为,请与本人联系,本人会及时删除。
3· 尊重成果,本文将用的参考文献所有给出,向无私的工程师,爱好者致敬。