QML地图Map中提供了供绘制图形的组件,例如MapPolyline,MapCircle等,但是这些组件在绘制复杂轨迹时就显得功能不够全面,因此我将QPainterPath在Map中进行使用并进行绘制,并使用C++和Qml中的函数进行相互调用计算获取点屏幕坐标和经纬度坐标。例子中使用了QPainterPath的QPainterPath::pointAtPercent获取绘制的轨迹全过程中的各个位置的经纬度。效果如图:

QML主要功能为地图显示,其中Plugin中定义的路径为我地图瓦片存放路径,你们需要修改为自己的或者直接使用在线地图。我们自定义了一个类 MapPainter,该类继承至QQuickPaintedItem,并通过元对象系统注册至QML中,覆盖到Map上方作为画布使用。

Demo项目地址:

https://download.csdn.net/download/zjgo007/87259998https://download.csdn.net/download/zjgo007/87259998https://github.com/zjgo007/QmlDemo/tree/master/MapPainterhttps://github.com/zjgo007/QmlDemo/tree/master/MapPainter

main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtLocation 5.9
import QtPositioning 5.9
import QtQuick.Controls 2.9import MapPainter 1.0Window {id:windowwidth: 640height: 480visible: truetitle: qsTr("Map Painter Path")Plugin {id: mapPluginname: "osm" // "mapboxgl", "esri", ...PluginParameter{//自定义地图瓦片路径name:"osm.mapping.offline.directory"value: "G:/Map/"}PluginParameter{name:"osm.mapping.offline.maptiledir"value:true}}Map {id: myMapcenter: QtPositioning.coordinate(24,104)anchors.fill: parentplugin: mapPluginzoomLevel: 8color: "#00000000"copyrightsVisible: falseactiveMapType: supportedMapTypes[2]//        onVisibleRegionChanged: {//Qt 5.15以上使用
//            mapPainter.mapRegionChanged()
//        }onCenterChanged: {//Qt 5.15以下使用mapPainter.mapRegionChanged()}onZoomLevelChanged: {//Qt 5.15以下使用mapPainter.mapRegionChanged()}MapPainter{id:mapPainteranchors.fill: parent}MapQuickItem{id: anchorMarkerwidth: 50height: 36anchorPoint.x: image.width/2anchorPoint.y: image.heightcoordinate: myMap.centersourceItem: Item{Image {id:imagesource: "qrc:/anchor.png"sourceSize.height: 36sourceSize.width: 50}Text {id: labely:-15color: "#00ffff"text: qsTr("")font.bold: truefont.pointSize: 11font.family: "微软雅黑"}}}MouseArea {id: mouseArea_measureanchors.fill: parentonClicked: {var coordinate = myMap.toCoordinate(Qt.point(mouse.x, mouse.y))mapPainter.addPathPoint(mouse.x, mouse.y,coordinate)anchorMarker.coordinate = coordinate}}}Slider {id: sliderx: 430y: 10stepSize: 0.01value: 1onValueChanged: {var coordinate = mapPainter.mapPathData(value)anchorMarker.coordinate = coordinatelabel.text = "("+coordinate.latitude.toFixed(4)+","+coordinate.longitude.toFixed(4)+")"}}Component.onCompleted: {mapPainter.setQmlObject(window)}function transGeoToPoint(coordinate){return myMap.fromCoordinate(coordinate,false)}function transPointToGeo(pointf){return myMap.toCoordinate(pointf,false)}
}

其中需要注意的是,在QML的Component.onCompleted信号发出后,需要该QML的QObject传递至MapPainter中,便于在C++中调用qml里定义的函数,这两个函数用于经纬度坐标和屏幕坐标转换。

Component.onCompleted: {mapPainter.setQmlObject(window)}function transGeoToPoint(coordinate){return myMap.fromCoordinate(coordinate,false)}function transPointToGeo(pointf){return myMap.toCoordinate(pointf,false)}

在C++中,addPathPoint(qreal x,qreal y,QGeoCoordinate coordinate)函数用于传入鼠标点击位置的屏幕坐标和经纬度坐标。mapRegionChanged()用于标记当前地图已被平移或者缩放,需要重新绘制轨迹。

同时自定义了类GeoPainterPath,该类记录了鼠标绘制轨迹的点位置和绘制方式,我只简单的放了MoveTo和LineTo,其他绘制方式可自行添加。

mappainter.h

#ifndef MAPPAINTER_H
#define MAPPAINTER_H#include <QQuickPaintedItem>
#include <QObject>
#include <QPainter>
#include <QPainterPath>
#include <QGeoCoordinate>class GeoPainterPath
{
public:GeoPainterPath() {}~GeoPainterPath(){}enum PainterType{None,MoveTo,LineTo};void addGeoPath(PainterType type,QGeoCoordinate coordinate);PainterType painterType(int index);QGeoCoordinate coordinate(int index);int size();void clear();private:QList<PainterType> typeList;QList<QGeoCoordinate> geoList;
};class MapPainter : public QQuickPaintedItem
{Q_OBJECT
public:MapPainter(QQuickItem *parent = nullptr);~MapPainter();virtual void paint(QPainter *painter) Q_DECL_OVERRIDE;Q_INVOKABLE void setQmlObject(QObject* object);public slots:void addPathPoint(qreal x,qreal y,QGeoCoordinate coordinate);void updatePainterPath();void mapRegionChanged();QGeoCoordinate mapPathData(qreal percent);private:QPainterPath* testPath;bool pathDirty;GeoPainterPath mGeoPainterPath;QObject* qmlObject;
};#endif // MAPPAINTER_H

mappainter.cpp

#include "mappainter.h"MapPainter::MapPainter(QQuickItem *parent):QQuickPaintedItem(parent),pathDirty(false)
{testPath = new QPainterPath();connect(this,&QQuickPaintedItem::widthChanged,this,&MapPainter::mapRegionChanged);connect(this,&QQuickPaintedItem::heightChanged,this,&MapPainter::mapRegionChanged);
}MapPainter::~MapPainter()
{delete testPath;
}void MapPainter::paint(QPainter *painter)
{if(pathDirty)updatePainterPath();painter->setPen(QPen(QColor("red"), 2, Qt::SolidLine,Qt::RoundCap, Qt::RoundJoin));painter->drawPath(*testPath);
}void MapPainter::setQmlObject(QObject *object)
{qmlObject = object;
}void MapPainter::addPathPoint(qreal x, qreal y, QGeoCoordinate coordinate)
{if(testPath->elementCount()==0){testPath->moveTo(x,y);mGeoPainterPath.addGeoPath(GeoPainterPath::MoveTo,coordinate);}else{testPath->lineTo(x,y);mGeoPainterPath.addGeoPath(GeoPainterPath::LineTo,coordinate);}update();
}void MapPainter::updatePainterPath()
{if(qmlObject){testPath->clear();int size = mGeoPainterPath.size();for(int i=0;i<size;i++){QGeoCoordinate coordinate = mGeoPainterPath.coordinate(i);QVariant mapPointVar;QMetaObject::invokeMethod(qmlObject,"transGeoToPoint",Qt::DirectConnection,Q_RETURN_ARG(QVariant,mapPointVar),Q_ARG(QVariant,QVariant::fromValue(coordinate)));GeoPainterPath::PainterType painterType = mGeoPainterPath.painterType(i);QPointF mapPoint = mapPointVar.toPointF();switch (painterType) {case GeoPainterPath::MoveTo:testPath->moveTo(mapPoint);break;case GeoPainterPath::LineTo:testPath->lineTo(mapPoint);break;default:break;}}pathDirty = false;}
}void MapPainter::mapRegionChanged()
{pathDirty = true;update();
}QGeoCoordinate MapPainter::mapPathData(qreal percent)
{QPointF pointf = testPath->pointAtPercent(percent);QVariant coordinateVar;QMetaObject::invokeMethod(qmlObject,"transPointToGeo",Qt::DirectConnection,Q_RETURN_ARG(QVariant,coordinateVar),Q_ARG(QVariant,QVariant::fromValue(pointf)));return coordinateVar.value<QGeoCoordinate>();
}void GeoPainterPath::addGeoPath(PainterType type, QGeoCoordinate coordinate)
{typeList.append(type);geoList.append(coordinate);
}GeoPainterPath::PainterType GeoPainterPath::painterType(int index)
{if(index>=typeList.size()){return PainterType::None;}return typeList.at(index);
}QGeoCoordinate GeoPainterPath::coordinate(int index)
{if(index>=geoList.size()){return QGeoCoordinate();}return geoList.at(index);
}int GeoPainterPath::size()
{return geoList.size();
}void GeoPainterPath::clear()
{typeList.clear();geoList.clear();
}

Demo项目地址:https://github.com/zjgo007/QmlDemo/tree/master/MapPainterhttps://github.com/zjgo007/QmlDemo/tree/master/MapPainter

QML地图Map中使用QPainterPath,并显示任意点经纬度位置相关推荐

  1. 请把学生名与考试分数录入到Map中,并按分数显示前三名成绩学员的名字

    请把学生名与考试分数录入到Map中,并按分数显示前三名成绩学员的名字. public class MapTest {@SuppressWarnings("unchecked")@T ...

  2. QML Map中测距——QtLocation轻量级地图应用学习

    QML Map中测距 1. 实现思路 2. 实现代码及git链接 本文转载于:QML QtLocation轻量级地图应用学习:实现测距功能 所有的热爱都要不遗余力,真正喜欢它便给它更高的优先级,和更多 ...

  3. QML 地图修改插件源码(三),Map在Plugin中设置加载地图类型

    常用的地图种类分为交通图,地形图,卫星图等等,在QML的Map(以OSM地图为例)中提供activeMapType属性用于读取当前显示的地图类型(注意:该属性为只读属性,不能用于赋值),QML中地图的 ...

  4. QML QtLocation地图应用学习-1:在Map中展示图元 Item

    目录 0.前言 1.开始 2.在Map中展示图元 3.一个完整的例子 4.Bug:当其他控件具有焦点时,地图上有灰白色方块 0.前言 Qt Location模块可用于轻量级的地图应用开发,不过官方示例 ...

  5. QML地图中使用MapItemView

    在QML地图上,我们可以自定义的画圆,画方,画线等等.当我们需要有较多的数据需要在地图上展示时,通过动态新增的方式很明显不利于管理和维护,因此用到MapItemView. MapItemView用于展 ...

  6. QML 地图修改插件源码(四),Map根据目录作为索引加载地图瓦片

    QML中的地图(以OSM为例)在使用过程中会发现当地图层数很多时,特别是如果使用离线地图且地图层级较多时地图会变得很卡(在线地图加载的层级数多且不清除缓存时也会卡),原因在于QML地图插件对地图瓦片的 ...

  7. ROS中base_link, odom, fixed_frame, target_frame和虚拟大地图map的关系

    前面已经介绍了如何使用URDF建造机器人小车并显示在Rviz的仿真环境里面,但是小车是静止的.下面介绍如何让它在Rviz里面动起来,并理清URDF,TF 和 odom 的关系. 1. ROS中base ...

  8. Echarts显示自定义标注点/地图map引导线

    Echarts显示自定义标注点/地图map引导线 先贴效果.这里实现了 1.地图上县区名的显示,鼠标移入显示相应的项目数(如下图东源县) 2.地图上增加自定义地图(这里增加了没有的高新区&市辖 ...

  9. ANDROID项目中嵌入高德地图(一)配置环境+显示地图

    最近在做项目中嵌入高德地图的工作,觉得有必要记录一下嵌入过程,虽然高德官方给说明文档了,但有写并不明确需要去查类,查资料,再此把过程记录一下. 一.显示地图 1.配置AndroidManifest.x ...

最新文章

  1. UITableView性能提升和优化(第3章) 之一
  2. Codeforces Round #628 (Div. 2) F. Ehab‘s Last Theorem dfs树
  3. 【2019牛客暑期多校训练营(第一场) - A】Equivalent Prefixes(单调栈,tricks)
  4. 华为杯数学建模优秀论文_【优秀论文】2019数维杯国际大学生数学建模竞赛B题优秀论文...
  5. PHP服务Fcgi进程及PHP解析优化
  6. [AngularJS] 理解AngularJS Directive中的Scope
  7. Java反射机制(Reflection)
  8. Linux(五):Ubuntu 16.04 更改系统语言为简体中文(Chinese simplified)
  9. Android开发笔记(一)像素的单位
  10. 金三银四网络面经之 DNS 详解!
  11. 智能客户—ERP技术新方向
  12. 【relations】MMD镜头+动作打包下载.zip
  13. AUTOCAD——矩形命令
  14. Ps制作的立体字效果
  15. ^^^ 存货盘盈盘亏的账务处理 Accounting for Inventory Profit and Inventory Loss with Goods Stock...
  16. 九峰影业创始人_九峰百度百科
  17. c语言0x1234占两个字节,C语言考试必考知识点
  18. 安卓APP——网页访问(WebView)
  19. 计算机专业eng4u,加拿大高中文凭ossd项目之ENG4U英语4U课程内容介绍!
  20. cad怎么倒圆角_学不好CAD怎么办?9个实用的CAD技巧,让你轻松玩转CAD

热门文章

  1. JMeter性能测试实现与分析分享
  2. ID-51A Plus2的D-Star Terminal Mode发信
  3. Docker - 容器内应用和外部非容器应用互相访问方法
  4. 解决Ubuntu或其他发行版本安装IDEA提示'tools.jar' is not in IDEA classpath
  5. 如何利用动态影像提升网页魅力
  6. excel图表技巧:如何用填充单元格制作比率分析图
  7. jenkins自动构建部署vue
  8. 电商平台-订单表的设计
  9. Vue-cli是何物
  10. 三相桥式全控整流电路 matlab,三相全控桥式整流电路Matlab仿真