QML QtLocation轻量级地图应用学习:实现自己的plugin加载瓦片地图

Qt Location模块中的plugin默认只有 "esri"、"mapbox"、"osm"、"here",一般我们需要换成自己的数据源,github 上有人做了谷歌地图和其他地图的 plugin 。而我目前的需求是加载本地瓦片地图,所以准备实现一个自己的 plugin 。

1.了解如何自定义 plugin 

我们可以通过查看 Qt Location 相关文档,了解自定义 plugin 的步骤:https://doc.qt.io/qt-5/qtlocation-geoservices.html

文档上提到了两点,给插件写一个json描述文件;继承 QGeoServiceProviderFactory 并实现其部分接口。

对于 json 文件的 Features 字段的内容,可以参考:https://doc.qt.io/qt-5/qgeoserviceprovider.html。比如我目前做这个只用到了瓦片加载,那么可以这样写(写的Online实际上是自己处理的网路请求加载本地数据):

{
    "Keys": ["mymap"],
    "Provider": "mymap",
    "Version": 100,
    "Experimental": false,
    "Features": [
        "OnlineMappingFeature"
    ]
}

对于接口实现部分,插件实现者需要继承QGeoServiceProviderFactory以及要为其提供实现的许多ManagerEngine类的子类(机器翻译),如果插件不提供对应引擎,则相关函数应返回0(nullptr)。如果要制作自己的 plugin 加载瓦片,需要重写createMappingManagerEngine处理相关请求来实现映射。

当然,只是看文档还不足以自己做一个插件,需要参考已有的实现,如:

Qt源码的实现: qt-everywhere-src-5.12.4\qtlocation\src\plugins\geoservices\osm\osm.pro

GitHub:https://github.com/vladest/googlemaps

GitHub:https://github.com/wangpengcheng/OfflineMapTest

2.实现中的一些关键点

目前的实现我只做了瓦片的请求,也就是继承 QGeoServiceProviderFactory 类后实现其 createMappingManagerEngine 接口。具体的请求由 QGeoTileFetcher 的子类来完成,我们继承他后实现 getTileImage 接口。

对于一些请求参数,我是通过 QGeoServiceProviderFactory 虚函数接口中的 parameters 参数来捕获的,我们可以在QML中通过给 Plugin 添加 PluginParameter 来传递参数:


        plugin: Plugin {
            name: "mymap" //"esri" "mapbox" "osm" "here"

            PluginParameter {
                name: "baseUrl"
                value: applicationDirPath+"/dianzi_gaode_ArcgisServerTiles/_alllayers"
            }
            PluginParameter {
                name: "format"
                value: "png"
            }
        }

目前也有一些没解决的问题,如请求的 url 不对的话程序会很卡;访问某个瓦片后Qt会自己生成缓存,目前还不知道怎么设置路径以及取消缓存(AppData\Local\cache目录)。

(2020-1-18)后来发现之前自定义的模块加载了 cache 但是不会释放,于是 Map 切换多次的话内存会占用很多,参考源码之后借用 QGeoFileTileCache 类来管理瓦片缓存,愉快的解决了 cache 没释放的问题。

3.实现效果及源码

实现效果如下图,源码中带有部分瓦片地图,可以直接运行。要注意的是不同的 Qt 版本可能 Location 模块有些接口不同,我使用的 Qt5.12 来制作,一些旧版本请自行查看 Qt 源码来修改。

QML QtLocation轻量级地图应用学习:实现自己的plugin加载瓦片地图_第1张图片

代码中有个 MyQtLocation.pro 用于运行示例,示例是静态加载的 plugin 。Plugin文件夹下有个单独的 pro文件用于生成 lib dll,生成动态库之后放到 Qt 安装目录的插件目录下(如 E:\Qt\Qt5.12.6\5.12.6\msvc2017\plugins\geoservices ),就可以在别的项目中使用这个 dll 了。

至此,一个简单的瓦片地图插件就完成了,如果要自己做一定要看文档和源码。

代码 github 链接:https://github.com/gongjianbo/MyQtLocation

 

你可能感兴趣的:(QML,三言两语,QtLocation)