通过Qml的map组件可以快速构建地图应用,设计中需要在地图上实时显示海量数据点(预计万点以上),考虑Qml、c++结合的方式,前端使用Qml显示,后端使用c++进行数据处理。由于刚接触Qml不久,本文主要记录作者急于求成的开发过程,边学边用,很多知识点存在理解不深的情况,若使用请慎重。
急于求成的特点就是知识零散、不系统,所以Qml开发的基础过程本文略过不讲(讲不清楚),下面急入主题。
1、目标
本节目标:
使用Qml创建一个地图基础应用。地图放大、缩小、移动,增加标注线、矩形等图元。
本节难度:★★★★★(万事开头难)
葫芦在此
如葫所示,内容包括
1)地图背景
2)左上角显示地图放大等级、鼠标点击位置
3)三个区域圆圈,设置区域背景颜色
2、实现过程
1)新建Quick工程
2)创建完成后,打开main.qml,添加代码生成地图窗口。
import QtQml 2.12
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello map") //看的出来,这是专业标题
visibility: Window.Maximized // 设置窗口最大化
Map {
id: item_map
anchors.fill: parent
anchors.topMargin:0
opacity: 0.99
plugin: Plugin{
//参见文档https://doc.qt.io/qt-5.12/qml-qtlocation-plugin.html
//首选插件语言环境的有序列表,但是貌似没啥用
locales: "zh-CN"
//插件的名称
//osm需要把openssl的dll放到运行目录
//esri默认就能用,mapbox的我这里加载不了,here的不知道咋用
//esri默认这个图成都那里不对(放大后)
name: "osm" // "mapboxgl", "esri", "osm"...
//首选插件名称的有序列表,设置了name值时无效
//preferred: ["here","osm"]
//选择附加到哪个服务插件时Plugin对象所需的功能集,设置了name值时无效
//required: Plugin.AnyMappingFeatures | Plugin.AnyGeocodingFeatures
}
//初始中心点-成都
center: QtPositioning.coordinate(centerLat, centerLon)
//初始缩放等级
zoomLevel: mapZoomReset
//最大缩放等级
maximumZoomLevel: 15
//最小缩放等级
minimumZoomLevel: 5
//背景色,没有正常加载时显色的图块颜色
color: "green"
//自定义属性
property real mapZoomReset : 12
property var mouseCoord : center
//可供在外部初始化
property real centerLat : 30.67
property real centerLon : 104.07
}
}
运行结果
恭喜,第1步成功了!是的,借用的别人的代码(注释完整部分,感谢各路大神分享,丝滑剪切,开心微改)。
核心内容:
map组件:定义地图的中心,缩放等级,plugin等属性;
plugin属性:选择加载的地图类别;
4)继续,获取鼠标点击位置坐标
import QtQml 2.12
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello map") //看的出来,这是专业标题
visibility: Window.Maximized // 设置窗口最大化
Map {
id: item_map
anchors.fill: parent
anchors.topMargin:0
opacity: 0.99
plugin: Plugin{
//参见文档https://doc.qt.io/qt-5.12/qml-qtlocation-plugin.html
//首选插件语言环境的有序列表,但是貌似没啥用
locales: "zh-CN"
//插件的名称
//osm需要把openssl的dll放到运行目录
//esri默认就能用,mapbox的我这里加载不了,here的不知道咋用
//esri默认这个图成都那里不对(放大后)
name: "osm" // "mapboxgl", "esri", "osm"...
//首选插件名称的有序列表,设置了name值时无效
//preferred: ["here","osm"]
//选择附加到哪个服务插件时Plugin对象所需的功能集,设置了name值时无效
//required: Plugin.AnyMappingFeatures | Plugin.AnyGeocodingFeatures
}
//初始中心点-成都
center: QtPositioning.coordinate(centerLat, centerLon)
//初始缩放等级
zoomLevel: mapZoomReset
//最大缩放等级
maximumZoomLevel: 15
//最小缩放等级
minimumZoomLevel: 5
//背景色,没有正常加载时显色的图块颜色
color: "green"
//自定义属性
property real mapZoomReset : 12
property var mouseCoord : center
//可供在外部初始化
property real centerLat : 30.67
property real centerLon : 104.07
//信息提示框
Rectangle{
anchors.left: parent.left
anchors.top: parent.top
height: item_center.height+20
width: item_center.width+20
radius: 3
color: "black"
opacity: 0.8
Text{
id: item_center
x: 10
y: 10
color: "white"
font.pixelSize: 16
font.bold: true
//展示缩放等级 和 map的中心点经纬度
text: "zoom level:"+Math.floor(item_map.zoomLevel)+
" 位置:"+item_map.mouseCoord.latitude+
" "+item_map.mouseCoord.longitude
}
}
//响应鼠标点击事件,鼠标点击时,显示鼠标位置坐标
MouseArea {
anchors.fill: parent
onClicked: {
var coord = item_map.toCoordinate(Qt.point(mouse.x, mouse.y));
item_map.mouseCoord = coord;
console.log("Latitude: " + coord.latitude + ", Longitude: " + coord.longitude);
//发射信号
mouse.accepted = true;
//此处设置选定,用于改变其它item的focus状态
focus = true;
}
}
}
}
运行结果
恭喜,第2步成功了!是的,也是借用的别人的代码(再次感谢各路大神分享,开心加倍)。
核心内容:
Rectangle:左上角显示提示信息;
MouseArea:响应鼠标事件,获取点击位置的坐标;
5)继续,增加区域圆圈
import QtQml 2.12
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtLocation 5.12
import QtPositioning 5.12
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello map") //看的出来,这是专业标题
visibility: Window.Maximized // 设置窗口最大化
Map {
id: item_map
anchors.fill: parent
anchors.topMargin:0
opacity: 0.99
plugin: Plugin{
//参见文档https://doc.qt.io/qt-5.12/qml-qtlocation-plugin.html
//首选插件语言环境的有序列表,但是貌似没啥用
locales: "zh-CN"
//插件的名称
//osm需要把openssl的dll放到运行目录
//esri默认就能用,mapbox的我这里加载不了,here的不知道咋用
//esri默认这个图成都那里不对(放大后)
name: "osm" // "mapboxgl", "esri", "osm"...
//首选插件名称的有序列表,设置了name值时无效
//preferred: ["here","osm"]
//选择附加到哪个服务插件时Plugin对象所需的功能集,设置了name值时无效
//required: Plugin.AnyMappingFeatures | Plugin.AnyGeocodingFeatures
}
//初始中心点-成都
center: QtPositioning.coordinate(centerLat, centerLon)
//初始缩放等级
zoomLevel: mapZoomReset
//最大缩放等级
maximumZoomLevel: 15
//最小缩放等级
minimumZoomLevel: 5
//背景色,没有正常加载时显色的图块颜色
color: "green"
//自定义属性
property real mapZoomReset : 12
property var mouseCoord : center
//可供在外部初始化
property real centerLat : 30.67
property real centerLon : 104.07
//设置背景色
MapQuickItem{
id: rad_bk
zoomLevel: 10 //和缩放等级一起放大缩小
coordinate: QtPositioning.coordinate(item_map.centerLat, item_map.centerLon)
anchorPoint: Qt.point(sourceItem.width/2,sourceItem.height/2)
sourceItem: Rectangle{
width: 300
height: 300
radius: 150
color: "green"
opacity: 0.1 //使用透明度
}
}
//画最外圆线
MapQuickItem{
id: rad_0
zoomLevel: 10 //和缩放等级一起放大缩小
coordinate: QtPositioning.coordinate(item_map.centerLat, item_map.centerLon)
anchorPoint: Qt.point(sourceItem.width/2,sourceItem.height/2)
sourceItem: Rectangle{
width: 300
height: 300
radius: 150
color: "transparent" //使用透明,只显示边框
border.color: "green"
border.width: 1
opacity: 0.3
}
}
//画中间圆线
//在地图上显示任意Qt Quick对象
MapQuickItem{
id: rad_1
//缩放等级默认0固定大小,否则会和缩放等级一起放大缩小
zoomLevel: 10
//指示的坐标点
coordinate: QtPositioning.coordinate(item_map.centerLat, item_map.centerLon)
//sourceItem左上角相对于coordinate的偏移
anchorPoint: Qt.point(sourceItem.width/2,sourceItem.height/2)
//Qt Quick对象
sourceItem: Rectangle{
width: 200
height: 200
radius: 100
color: "transparent"
border.color: "yellow"
border.width: 1
opacity: 1
}
//Qt5.14加了一个淡入属性autoFadeIn
}
//画最内圆线
MapQuickItem{
id: rad_2
zoomLevel: 10 //和缩放等级一起放大缩小
coordinate: QtPositioning.coordinate(item_map.centerLat, item_map.centerLon)
anchorPoint: Qt.point(sourceItem.width/2,sourceItem.height/2)
sourceItem: Rectangle{
width: 100
height: 100
radius: 50
color: "transparent" //背景透明,但边框不透明
border.color: "red"
border.width: 1
opacity: 0.5
}
}
//信息提示框
Rectangle{
anchors.left: parent.left
anchors.top: parent.top
height: item_center.height+20
width: item_center.width+20
radius: 3
color: "black"
opacity: 0.8
Text{
id: item_center
x: 10
y: 10
color: "white"
font.pixelSize: 16
font.bold: true
//展示缩放等级 和 map的中心点经纬度
text: "zoom level:"+Math.floor(item_map.zoomLevel)+
" 位置:"+item_map.mouseCoord.latitude+
" "+item_map.mouseCoord.longitude
}
}
//响应鼠标点击事件,鼠标点击时,显示鼠标位置坐标
MouseArea {
anchors.fill: parent
onClicked: {
var coord = item_map.toCoordinate(Qt.point(mouse.x, mouse.y));
item_map.mouseCoord = coord;
console.log("Latitude: " + coord.latitude + ", Longitude: " + coord.longitude);
//发射信号
mouse.accepted = true;
//此处设置选定,用于改变其它item的focus状态
focus = true;
}
}
}
}
运行结果
恭喜,第3步成功了!
核心内容:
MapQuickItem:地图内添加组件使用该模块,具有coordinate属性,通过设置坐标值进行位置定位。
zoomLevel:设置不为0,则随地图进行缩放;设置为0则固定大小,不随地图缩放。
圆圈设计:没有直接空心圆的组件,这里使用透明色、边框色、边框宽度进行配置,达到预期效果,比设计代码画空心圆省心不少(小坑一个)
color: "transparent" //使用透明,只显示边框
border.color: "green"
border.width: 1
3、总结
1)Qml快速构建地图应用,确实比较方便(比C++);
2)主要组件:map、MapQuickItem,plugin、zoomLevel等属性;
3)矩形、鼠标响应事件,与常规Qml处理相同;
本节目标完成,加加油!
源码下载:
【免费】Qml地图应用示例,包括地图显示、区域线、获取鼠标位置等源程序资源-CSDN文库
脚印--不断寻找的轮子最终可能是自己--