QT实现加载百度离线地图

792 阅读4分钟

在Qt中加载百度地图需要用到网络浏览器,在此采用webEngine模块,然后用webchannel进行qt与HTML/JavaScript的交互。
需求描述:软件加载百度地图,用鼠标在地图上选点,并进行标号,每次加1,最后连成一条路径,为后期工作做准备。

百度地图API应用

  • 采用百度离线地图API2.1版本,网上均可以下载到,然后放到项目debug文件夹下
  • 瓦片地图下载,可以采用全能地图下载器,下载好后放到指定文件夹
  • 复制其中一个demo文件,根据自己需要的功能进行添加

地图展示



  • var
    map
    =
    new
    BMap.Map(
    "map_demo"
    ,mapOptions);
    // 设置街道图为底图




  • var
    point =
    new
    BMap.Point(
    120.393751
    ,
    36.065743
    );
    // 创建点坐标




  • map
    .centerAndZoom(point,
    13
    );
    // 初始化地图,设置中心点坐标和地图级别



鼠标点击标记加序号

用addEventListener("click",function(e))对点击事件进行监听,参数e会返回当前点的地理位置,然后在此处用Marker添加标记,在实现每次标记加1时,因为标记本身是一个图片,因此可以考虑对标记加标签(定义一个全局的i,每点击一次加1),然后调整下位置(为了美观),背景设置为透明,基本就可以实现所要的效果。标签的颜色和背景可以使用Label类下的setStyle方法设置:



  • label
    .setStyle
    ({



  • color
    :
    "white"
    ,



  • backgroundColor:
    "0"
    ,



  • border:
    "0"
    ;



  • fontsize
    :
    "13px"




  • });


生成轨迹

创建一个全局空数组,在上一步中监听点击事件,参数e返回位置点,将此点push到数组中,在生成轨迹时将数组序列直接传入Polyline ,然后map.addOverlay(polyline)即可加载标签。

具体的类和方法参见

Qt与html交互

地图全屏显示

用wenEngine全屏显示地图时的代码:



  • //mainwidow中的函数




  • view=
    new
    QWebEngineView(this);



  • view->load(url);



  • view->show();


添加:



  • void MainWindow::resizeEvent(QResizeEvent *)



  • {



  • view->resize(this->size());



  • }


地图在一个 widget中显示

在UI设计界面,我的qt5.9版本是找不到wenEngineView 组件的,解决方法:在ui设计页面,拖入widgets控件,然后提升为QWebengineView,如图所示:


在mainwindow函数中进行webengine初始化:



  • QWebEnginePage *page=
    new
    QWebEnginePage(this);



  • QWebChannel *channel=
    new
    QWebChannel(this);



  • page->load(url);



  • page->setWebChannel(channel);



  • ui->webEngine->setPage(page);


新版的Qt摒弃了webkit,采用webengine,在交互上简单了很多,例如生成路径按钮的槽函数:



  • void MainWindow::on_generatetrack_clicked()



  • {



  • QString cmd=
    "generate_track()"
    ;



  • ui->webengine->page()->runJavaScript(cmd);



  • }


其中generate_track()为html文件中的函数,只需要一条语句即可实现交互。
最终效果如图:

后期加的功能1

功能:实现小车沿路径运动
有两种方案:

  • 采用百度地图开源库LuShu实现
  • 采用定时器,定时将小车作为标注显示在路径点上。

第二种方案适合于路径点很密集,很多的情况,才能看出效果。由于这个项目是采用鼠标选几个位置,因此适合采用第一种方案。

实现部分:

  • 添加lushu的js文件

<script type="text/javascript" src="tools/LuShu_min.js"></script>

  • 根据上边保存的路径点数组,实例化一个全局lushu对象,放在generate_track函数里


  • lushu=
    new
    BMapLib.LuShu(
    map
    ,track_point,{



  • icon:icon1,
    //图标可以自己添加,也可以默认为百度的红色标注小气球




  • speed:
    3000
    ,



  • autoView:
    false
    ,



  • enableRotation:
    true




  • });


  • 最后在需要开始运动的函数里添加下面函数就可以
lushu
.start

();后期加的功能2

功能:对已经选择的路径点通过输入经纬度进行修改(生成路径前后均可修改)
首先在Qt中添加以下代码(前提是在界面中设置好文本框和修改按钮):



  • void MainWindow::on_modify_clicked()



  • {



  • QString number=ui->orderNumber->text();



  • QString lng=ui->lngEdit->text();



  • QString lat=ui->latEdit->text();



  • QString cmd=QString(
    "modifyMarker(\"%1\",\"%2\",\"%3\")"
    ).arg(number).arg(lng).arg(lat);
    //modifyMaker是html文件中的函数




  • ui->webengine->page()->runJavaScript(cmd);



  • }


在html文件中添加:



  • function modifyMarker(number,lng,lat){



  • allMarker=map.getOverlays();
    //保存所有标注




  • var
    newpoint=
    new
    BMap.Point(lng,lat);



  • allMarker[number
    -1
    ].setPosition(newpoint);



  • track_point[number
    -1
    ]=newpoint;



  • if
    (allMarker[allMarker.length
    -1
    ].toString()!=
    "[object Marker]"
    ){
    //看array中最后一个元素是不是polyline




  • map.removeOverlay(polyline);
    //来判断生成路径之前




  • generate_track();
    //还是生成路径之后修改路径点




  • }



  • }


由于没有系统学习过JavaScript,其中if中的判断语句参考了下面图片中的方法,意思就是判断最后一个覆盖物是不是Marker对象。


在getOverlays()后不知道为什么多一个隐藏的标注,所以在选路径点时先清理一次所有的标注,即在选路径点的函数中首先添加:

map
.clearOverlays

();