最近想用Qml做地图的应用,看了看Qt官方的例子,使用QtLocation模块,代码倒是很简单,只要提供插件,后面的事情基本就都由QtLocation模块负责了,但是试用了Qt自带的几个插件("esri"、"mapbox"、"nokia"、"osm"),不是报连接错误就是地图显示不出来。正好之前折腾过QGroundControl地面站,也是用Qt做的,显示地图还是很顺利的,准备扒一扒代码仿一个。
折腾了很久才看明白,具体过程就不赘述了,直接上结果:
首先,是主窗口MainRootWindow.qml:
FlyView
{
id: flightView
anchors.fill: parent
}
这里调用FlyView.qml,转到FlyView:
FlyViewMap {
id: mapControl
planMasterController: _planController
rightPanelWidth: ScreenTools.defaultFontPixelHeight * 9
pipMode: !_mainWindowIsMap
toolInsets: customOverlay.totalToolInsets
mapName: "FlightDisplayView"
}
这里调用FlyViewMap.qml,转到FlyViewMap:
FlightMap {
id: _root
allowGCSLocationCenter: true
allowVehicleLocationCenter: !_keepVehicleCentered
planView: false
zoomLevel: QGroundControl.flightMapZoom
center: QGroundControl.flightMapPosition
这里直接就用了FlightMap.qml,再转到FlightMap:
这里就比较明确了,引用了
import QtLocation 5.3
Map {
id: _map
//-- Qt 5.9 has rotation gesture enabled by default. Here we limit the possible gestures.
gesture.acceptedGestures: MapGestureArea.PinchGesture | MapGestureArea.PanGesture | MapGestureArea.FlickGesture
gesture.flickDeceleration: 3000
plugin: Plugin { name: "QGroundControl" }
// https://bugreports.qt.io/browse/QTBUG-82185
opacity: 0.99
可以看到plugin用的是一个叫“QGroundControl”的插件,然后开始找如何引用的,在main.cc文件里查找插件的引用,如下:
Q_IMPORT_PLUGIN(QGeoServiceProviderFactoryQGC)
搜索QGeoServiceProviderFactoryQGC,发现在QGCLocationPlugin工程里,自此整个就可以连起来了。在QGeoServiceProviderPluginQGC.h文件中定义了QGeoServiceProviderFactoryQGC类,其继承于QGeoServiceProviderFactory类,这个类是QtLocation模块里的类,自定义的地图插件都需要继承这个类,整个思路就清晰了。
但是“QGroundControl”这个插件名字怎么对应起来的,查看官方的资料:Qt Location GeoServices | Qt Location 5.15.8,地图插件还需要提供一个json文件,在QGCLocationPlugin工程文件夹里找到qgc_maps_plugin.json文件,打开查看:
{
"Keys": ["qgc-maps"],
"Provider": "QGroundControl",
"Version": 101,
"Experimental": false,
"Features": [
"OnlineMappingFeature",
"OnlineGeocodingFeature",
"ReverseGeocodingFeature"
]
}
终于一切真相大白,话说还是应该先看看官方介绍再研究代码,不然直接看代码还真是有点摸不着头脑。
查看QGCLocationPlugin,除了Qt本身支持的几个地图,还提供Bing和GoogleMap,GoogleMap需要翻墙,有Bing的话也基本够用了,可以copy了😊。