Qt的QWebChannel和JS、HTML通信/交互驱动百度地图

本文重点来说一下,如何从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 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);
}

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>

这么多代码,看的你很焦躁,不用太细研究,里面只是定义了很多百度地图读取的方法,我们把重点放在几个点上(你可以在上面的源码注释中找到重点标记)

  • 【第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,然后你该怎么办就怎么办了。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QWebChannel是一种用于Qt应用程序和嵌入式Web页面之间进行互操作的通信机制。它允许Qt应用程序向Web页面暴露对象,并允许Web页面访问这些对象的属性和方法。同时,也允许Web页面向Qt应用程序发送消息和调用Qt应用程序的函数。 使用QWebChannel进行Qt和JavaScript之间的交互,需要遵循以下步骤: 1. 在Qt应用程序中创建一个QWebChannel对象,并将其绑定到一个QWebEngineView或QWebEnginePage对象上。 2. 在Qt应用程序中创建一个QObject的子类,该子类将作为Qt对象被暴露给Web页面。 3. 在Qt应用程序中将QObject对象注册到QWebChannel对象中。 4. 将QWebChannel对象传递给Web页面,通过JavaScript代码将其绑定到Web页面中的window对象上。 5. 在JavaScript代码中可以通过window对象访问到Qt应用程序中注册的QObject对象,调用其属性和方法。 6. 在Qt应用程序中可以通过QWebChannel对象接收Web页面发送的消息,以及调用Web页面中的JavaScript函数。 下面是一个简单的例子,演示了如何使用QWebChannel进行Qt和JavaScript之间的交互Qt代码: ```c++ // 创建一个QObject的子类,作为Qt对象被暴露给Web页面 class MyObject : public QObject { Q_OBJECT public: MyObject(QObject *parent = nullptr) : QObject(parent) {} public slots: void showMessage(const QString &message) { qDebug() << "Received message from web page:" << message; } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建一个QWebChannel对象,并将其绑定到一个QWebEngineView对象上 QWebEngineView view; QWebChannel channel; view.page()->setWebChannel(&channel); // 创建MyObject对象,并将其注册到QWebChannel对象中 MyObject obj; channel.registerObject("myObject", &obj); // 加载Web页面 view.load(QUrl("qrc:/index.html")); view.show(); return app.exec(); } ``` JavaScript代码: ```javascript // 将QWebChannel对象绑定到window对象上 new QWebChannel(qt.webChannelTransport, function(channel) { window.myObject = channel.objects.myObject; }); // 调用MyObject对象的showMessage函数 myObject.showMessage("Hello from web page!"); ``` 在上面的例子中,我们创建了一个名为MyObject的QObject子类,并将其注册到了QWebChannel对象中。在JavaScript代码中,我们通过调用QWebChannel构造函数,将QWebChannel对象绑定到window对象上,并通过window对象访问了MyObject对象的showMessage函数。当Web页面调用showMessage函数时,它将向Qt应用程序发送一个消息,Qt应用程序将通过QWebChannel对象接收到该消息,并调用MyObject对象的showMessage函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值