c++/Qt日志库实现

  • 前言
  • 需求
  • 流程图
  • 程序实现
    • 插件编写
      • 缓冲实现
      • 多地图加载
    • 程序加载
  • 最终实现
  • 下载地址
    • 测试程序下载地址
    • 源码下载地址
  • 缺陷
  • 最后
  • 参考

前言

相信大家在使用QT开发中难免会需要用到地图开发,目前主流是使用QWebEngineView调用浏览器,使用浏览器加载第三方api,如openlayers 和谷歌地图API等。但是这种优点是api支持度高非常简单,容易上手。但是缺点是没法缓冲地图资源,必须依赖地图服务器。
还有一种小众的解决方法是使用Qt自带的QtLocation(如果你的程序不准备使用qml为主的话,你基本就不需要往下看了),这篇文章就是介绍QtLocation的使用方法的。

需求

1.支持离线地图、在线天地图和本地缓冲地图
2.可以导入导出缓冲的在线资源

流程图

我认为讲半天废话,不放流程图的都是耍流氓

程序实现

插件编写

缓冲实现

1.这里实现了缓冲入库

class stMapTileData : public QObject
{Q_OBJECT
public://瓦片数据quint32    hash;    //瓦片图块位置HashQString    format;  //图片格式QByteArray byte;    //瓦片图片int        x;int        y;int        zoom;    //地图层级quint32    mapID;   //地图ID
};void CMapGeoFileTileCache::addToSqlite(const QGeoTileSpec &spec, const QString &format, const QByteArray &bytes)
{QSharedPointer<stMapTileData> tile = QSharedPointer<stMapTileData>(new stMapTileData);tile->hash   = CMapLoadSetting::getTileHash(spec.mapId(), spec.x(), spec.y(), spec.zoom());tile->format = format;//图片格式tile->byte   = bytes;   //瓦片图片tile->x      = spec.x();//xtile->y      = spec.y();//ytile->zoom   = spec.zoom();//地图层级tile->mapID  = spec.mapId();//地图ID//不阻塞,这里主要是写入速度太慢QMetaObject::invokeMethod(CMapEngineMgr::Instance()->getSqlThread().data(), "slot_writeSql",Qt::QueuedConnection, Q_ARG(QSharedPointer<stMapTileData>, tile));
}
void CSqlDataWorker::slot_writeSql()
{if (m_pQuery && !m_queue.isEmpty()){auto tile = m_queue.dequeue();//如果不存在就插入,存在就更新的方式;m_pQuery->prepare("INSERT INTO Tiles(hash, format, tile, size, x, y, zoom, mapID, dateTime) VALUES(?, ""?, ?, ?, ?, ?, ?, ?, ?)");m_pQuery->addBindValue(tile->hash);m_pQuery->addBindValue(tile->format);m_pQuery->addBindValue(tile->byte);m_pQuery->addBindValue(tile->byte.size());m_pQuery->addBindValue(tile->x);m_pQuery->addBindValue(tile->y);m_pQuery->addBindValue(tile->zoom);m_pQuery->addBindValue(tile->mapID);m_pQuery->addBindValue(QDateTime::currentDateTime().toMSecsSinceEpoch());if (m_pQuery->exec()) {//新的数据已存入} else {// Map数据已存在于数据库}m_pQuery->finish();}
}

2.这里实现是缓冲读取


QSharedPointer<QGeoTileTexture> CMapGeoFileTileCache::getFromSqlite(const QGeoTileSpec &spec)
{QSharedPointer<stMapTileData> tile(new stMapTileData) ;//创建一个瓦片//获取Hashtile->hash = CMapLoadSetting::getTileHash(spec.mapId(), spec.x(), spec.y(), spec.zoom());auto start = clock();//从数据库读取瓦片数据//阻塞等待返回,因为读取数据非常快,阻塞没有影响QMetaObject::invokeMethod(CMapEngineMgr::Instance()->getSqlThread().data(), "slot_readTile",Qt::BlockingQueuedConnection, Q_ARG(QSharedPointer<stMapTileData>, tile));qDebug() << "read time:" << clock() - start << "ms";if (tile->byte.isEmpty())return QSharedPointer<QGeoTileTexture>();QImage image;//一些来自服务器的瓷砖可能是有效的图像,但瓷砖获取器//也许可以将它们识别为不应该显示的方块。//如果是这种情况,瓷砖获取器应该在文件中写入“NoRetry”。if (isTileBogus(tile->byte)) {QSharedPointer<QGeoTileTexture> tt(new QGeoTileTexture);tt->spec  = spec;tt->image = image;return tt;}// 这是一个真正无效的图像。获取器应该再试一次。if (!image.loadFromData(tile->byte/*,tile->format.toLatin1()*/)) {handleError(spec, QStringLiteral("瓦片图像有问题"));return QSharedPointer<QGeoTileTexture>(0);}// 在这里转换它,而不是在每个QSGTexture::bind()中if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_ARGB32_Premultiplied)image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);addToMemoryCache(spec, tile->byte, tile->format);//添加到内存缓冲QSharedPointer<QGeoTileTexture> tt = addToTextureCache(spec, image);//添加瓦片到缓冲if (tt) {return tt;}return QSharedPointer<QGeoTileTexture>();
}

多地图加载

CMapUrlEngineMgr::CMapUrlEngineMgr(QObject *parent): QObject{parent}
{CMapProviderBase * pMapBase =  new CMapProviderTianDi(QGeoMapType::SatelliteMapDay,this); //天地图卫星图m_hashProvides["Tianditu Satellite"] =pMapBase;pMapBase->setLicense( CMapLoadSetting::Instance()->m_mapMapData["Tianditu Satellite"].strLicense);pMapBase->setFormat( CMapLoadSetting::Instance()->m_mapMapData["Tianditu Satellite"].strFormat);//m_hashProvides["Tianditu Street"] = new TiTiandituCiaMapProvider(this); //天地图路网标注信息图pMapBase = new CMapProviderOffLine(QGeoMapType::SatelliteMapDay,this); //离线卫星图m_hashProvides["OffLine Satellite"] = pMapBase;pMapBase->setLicense( CMapLoadSetting::Instance()->m_mapMapData["OffLine Satellite"].strLicense);pMapBase->setFormat( CMapLoadSetting::Instance()->m_mapMapData["OffLine Satellite"].strFormat);
}CMapGeoTiledMappingManagerEngine::CMapGeoTiledMappingManagerEngine(const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString):QGeoTiledMappingManagerEngine()
{//设置图层QGeoCameraCapabilities cameraCaps;cameraCaps.setMinimumZoomLevel(2.0);//最大缩放cameraCaps.setMaximumZoomLevel(18.0);//最小缩放 地图层级cameraCaps.setSupportsBearing(true);cameraCaps.setSupportsTilting(true);//    cameraCaps.setMinimumTilt(0);//    cameraCaps.setMaximumTilt(80);//    cameraCaps.setMinimumFieldOfView(20.0);//    cameraCaps.setMaximumFieldOfView(120.0);//    cameraCaps.setOverzoomEnabled(true);setCameraCapabilities(cameraCaps);//宏注册 QByteArray("TefeiMap") 由Json导入#define QGCGEOMAPTYPE(a,b,c,d,e,f)  QGeoMapType(a,b,c,d,e,f,QByteArray("demoMap"), cameraCaps)//获取所有的 地图 路径样式 包括 离线和天地图 都从这里获取QList<QGeoMapType> mapList;//地图瓦片引擎auto hashProviders = CMapEngineMgr::Instance()->getUrlEngine()->getProviderTable();for (auto cIt = hashProviders.cbegin(); cIt != hashProviders.cend(); ++cIt) {mapList.append(QGCGEOMAPTYPE(cIt.value()->getMapStyle(), cIt.key(), cIt.key(), false, false, CMapEngineMgr::Instance()->getUrlEngine()->getIdFromType(cIt.key())));}setSupportedMapTypes(mapList);//设置支持的映射类型//没有用QGeoFileTileCache,默认加载地缓存不会释放,还没找到原因,估计要分析它的源码//缓冲路径QString  strCacheDirectory = CMapLoadSetting::Instance()->m_strCacheSqlDir;//设置地图缓冲,如果不需要缓存,可设置setMaxDiskUsage 大小,限制到小内存,,//无法 注释setTileCache(); 注释后会默认缓冲图片//    QGeoFileTileCache* tileCache = new QGeoFileTileCache(cacheDirectory, this);auto tileCache = new CMapGeoFileTileCache(strCacheDirectory, this);//auto tileCache = new QGeoFileTileCache(strCacheDirectory, this);tileCache->setMaxDiskUsage(1024 * 1024);tileCache->setMaxMemoryUsage(1024 * 1024 * 100);//100m内存setTileCache(tileCache);//创建地图瓦片获取器//从网络中加载瓦片auto tileFetcher = new CMapGeoTileFetcher(parameters, this);setTileFetcher(tileFetcher);//结束m_prefetchStyle = QGeoTiledMap::PrefetchNeighbourLayer; //QGeoTiledMap::NoPrefetching;//没有预先存取 //可设置缓冲一些瓦片*error = QGeoServiceProvider::NoError;errorString->clear();}

程序加载

int main(int argc, char *argv[])
{//导入地图插件Q_IMPORT_PLUGIN(CMapGeoServiceProviderFactory);
}
Map{id:             mapwidth:          parent.widthheight:         parent.heightanchors.bottom: parent.bottomanchors.horizontalCenter: parent.horizontalCenterzoomLevel:      MapEngineMgr.getMapZoom().rawValue    //缩放等级center:         MapEngineMgr.getMapCenter()    //中心点//gesture.acceptedGestures: MapGestureArea.PinchGesture //支持的手势plugin:         Plugin { name: "demoMap" }//插件名称 对应 MapGeoTiledMappingManagerEngine cpp 第26行 和Json "Provider": "TefeiMap",visible:        truefunction updateActiveMapType() {for (var i = 0; i < map.supportedMapTypes.length; i++) {console.log("地图供应商",map.supportedMapTypes[i].name)//在这里可以切换地图if (fullMapName === map.supportedMapTypes[i].name) {map.activeMapType = map.supportedMapTypes[i]return}}}Component.onCompleted: {//加载完毕后 更新一次界面updateActiveMapType()}
}

最终实现

下载地址

测试程序下载地址

测试程序下载地址:

源码下载地址

CSDN:
GitHub:
GitLab:

缺陷

必须使用QML,而且API支持较少,文档较少,比不得openlayers这些成熟的前端地图框架。

最后

本人才疏学浅,还有很多不足,欢迎各位指出,也请收下留情,勿喷。

参考

1.qgroundcontrol地面站:http://qgroundcontrol.com/
2.龚建波 QML QtLocation地图应用学习-5:https://blog.csdn.net/gongjianbo1992/article/details/103655126

转载请注明出处谢谢。

QT地图QtLocation相关推荐

  1. linux qt地图开发教程,基于QT的电子地图的设计与实现

    [实例简介] 基于QT的电子地图的设计与实现 ,毕业设计论文,附上源码以及论文原文,Linux下系统可跑.. [实例截图] [核心代码] system ├── 正文.doc └── 系统 ├── de ...

  2. 64.qt quick-qml使用高德地图插件实现V2版本(新增:位置搜索、路径规划、轨迹编辑等)

    在61.章节里我们学习了如何实现一个map插件.所以本章来扩展内容.实现轨迹编辑等 bilibili视频预览:  bilibili链接 (之前的老版本,后面优化增加谷歌卫星了) 1.效果图展示 使用公 ...

  3. qt quick-qml高德地图实现V1版本(跨平台支持、无需浏览器内核,运行迅速,下个版本实现位置搜索)

    1.效果图展示  gif如下所示(文件有点大,已压缩) 2.demo介绍 支持跨平台linux/windows等,qt插件方式,非浏览器加载 支持缓存保存离线地图实现 支持地图转向.旋转.方位调整等 ...

  4. QML地图简介(1)

    一.地图插件介绍 1.qml提供了四个内建的地图在线插件"esri"."mapbox"."nokia"."osm",但是 ...

  5. Qt实现屏幕虚拟软键盘

    作者 QQ群:852283276 微信:arm80x86 微信公众号:青儿创客基地 B站:主页 https://space.bilibili.com/208826118 参考 Qt编写输入法V2018 ...

  6. qt怎么实现二维地图加载,用c++实现

    使用 Qt 可以使用 Qt 地图模块来实现二维地图加载.你需要在你的项目中包含 Qt 地图模块,然后使用 QMapWidget 类来显示二维地图.你还可以使用 QGeoMappingManager 类 ...

  7. 添加类iOS cocos2d 2游戏开发实战(第3版)

    这两天一直在学习添加类之类的问题,现在正好有机会和大家讨论一下. 第1章 简介 1 1.1 第3版中的新增内容 2 1.2 选择ios版cocos2d的来由 3 1.2.1 收费 3 1.2.2 开源 ...

  8. iOS cocos2d 2游戏开发实战(第3版)

    <iOS cocos2d 2游戏开发实战(第3版)> 基本信息 原书名:Learn cocos2d 2: Game Development for iOS 作者: (美)Steffen I ...

  9. iOS 5 cocos2d游戏开发实战(第2版)

    <iOS 5 cocos2d游戏开发实战(第2版)> 基本信息 作者: [美]Steffen Itterheim Andreas Low [作译者介绍] 译者: 同济大学苹果俱乐部 丛书名 ...

最新文章

  1. android listview 中的checkbox,Android中ListView与CheckBox的使用,及问题解决
  2. Rainbond 5.0正式发布, 支持对接管理已有Kubernetes集群
  3. OpenSSL库概述
  4. html下拉框选择后自动刷新,html select 下拉框刷新页面后保留上一次选择的值
  5. Swift自定义Class实现Hashable
  6. raw,qcow2虚拟磁盘挂载
  7. 王道训练营Day24——Linked
  8. git rm 和 rm 的区别
  9. Matlab2017b安装教程及破解失败方法
  10. 计算机 在职硕士报考条件,2022在职硕士-在职研究生报考条件-中公考研
  11. macd底背离的python_java尝试编写macd,试验顶背离底背离
  12. [云计算] 云使能技术包括哪些技术组件?
  13. flask框架----跨域
  14. PhotoShop cc合并多张静态图片为gif动画
  15. ubuntu查看电脑配置命令
  16. matlab封装的模块,matlab模块封装
  17. 【 shell 编程 】第1篇 变量
  18. 青少年ADHD双通路模型的神经相关性
  19. Hello MySQL(十三)——事务和锁
  20. [Python] GDAL/OGR操作矢量数据(shp、GeoJSON)

热门文章

  1. Conversion
  2. 欧文6 oracle aqua 测评,欧文6实战测评!详细说说
  3. Codeforces Educational Round#21 F(808F) Solution:网络流(最小割)
  4. 阿里百川能否让移动开发者“归海”?
  5. 泛娱乐生态倒逼,各大视频为何抢位3D动画?
  6. 2022icpc昆明
  7. 关联查询子查询效率简单比照
  8. 构建统一监管制度 加快数据要素立法修法
  9. discuz admin.php换名,discuz更换域名修改方法
  10. SQL Server 2005中的分区表(一):什么是分区表?为什么要用分区表?如何创建分区表?