Ubuntu下QT用QWebEngineView嵌入百度地图实现经纬度定位

发布时间:2026/9/8 1:42:34

Ubuntu下QT用QWebEngineView嵌入百度地图实现经纬度定位
简介面向需要在 Ubuntu 操作系统中集成百度地图的 Qt 开发者这份小体积示例包演示了如何借助 Qt 的网页视图组件加载本地网页文件并实现输入经纬度后显示对应位置。资源总共包含 9 个文件其中有 2 个网页页面、2 个 C 源文件、1 个头文件、1 个界面设计文件、1 个工程管理文件以及若干构建辅助文件压缩包整体仅 9KB结构清晰明了非常适合快速移植到已有项目中。关键实现思路可以从代码中直接读到先安装 Qt 基础开发包与网页引擎开发包在页面中引入百度地图脚本库布置经纬度输入框和定位按钮点击后利用地图坐标对象设置中心点并添加标记Qt 端则加载该页面并通过监听页面地址变化来调用页面中的定位函数完成桌面端与网页端的交互。如今已有 1231 人学习下载适合希望在 Qt 应用里快速加入地图能力的开发者。拿到材料后可以直接运行调试并能够在此基础上继续扩展自动补全、多点标记、地址解析等实用功能省去从零研究地图接口和混合编程调试的精力。 Ubuntu 下用 QT 写桌面程序想直接调用百度地图做界面展示很多人第一反应是去翻官方 SDK结果查一圈发现百度地图客户端 SDK 只有 Android、iOS、小程序这些端桌面端根本没给 QT 留接口。好在 QT 从 5.6 开始集成了基于 Chromium 内核的 QWebEngineView完全可以把百度地图的 HTML 网页当作一个控件嵌进窗口里。这篇文章把整个过程完整跑一遍申请百度地图 AK、编写可运行的地图 HTML、在 QT 工程里加载页面并输入经纬度定位代码可以直接抄去改。不管你是做 Ubuntu 桌面开发项目还是在工控机上用 QT 套一个地图显示模块只要需求定位是“嵌入式网页地图”这套方案都能用换成高德地图、天地图、Leaflet 也是同一个思路。1. 方案选型为什么用 QWebEngineView 嵌入百度地图1.1 需求拆分与技术栈这个需求拆开其实就三件事一个能渲染网页的组件一份包含百度地图 JS API 的 HTML以及 C 向网页传递参数的方法。对应到 QT 侧就是 QWebEngineView QLineEdit QPushButton 的组合。QWebEngineView 负责加载和渲染地图页面QLineEdit 接收用户输入的经纬度QPushButton 触发定位。定位动作的核心只是一行page()-runJavaScript()把坐标拼成 JS 函数调用丢给网页执行。整个架构就是“浏览器壳 Web 页面”的模式QT 只做宿主外壳和业务控制地图渲染、缩放、标注全部交给百度地图 API。好处很明显地图能力由官方维护后续想加 POI 搜索、路线规划只需要改 HTMLC 侧几乎不动。1.2 备选方案对比动手之前我也对比过其他路子方案维护成本地图功能适用场景QWebEngineView 地图 JS API低地图能力由官网更新搜索、路线、图层完整桌面端嵌入式地图QWebView QtWebKit极高Qt 5.5 后已移除受旧内核兼容性限制遗留项目维护自绘瓦片 QPainter高切片拼接逻辑自研只有最基础的地图显示纯离线场景启动外部浏览器最低完整不需要嵌入界面时排除法走下来QWebEngineView 是唯一“既能嵌入桌面界面、又不用自己造轮子”的方案这也是目前社区里做 QT 桌面地图的主流做法。1.3 C 与网页之间的三种通信方式C 向网页传参数常见的有三条路runJavaScript单向调用C 直接把 JS 代码丢给页面执行。适合“输入坐标 - 定位”这种场景。QWebChannel双向通道网页里的 JS 也能回调 C 对象。适合“点击地图 - 坐标回传 C”这种反向交互。URL 参数拼接加载时把坐标拼到 URL 问号后面。只适合初始化定位后期交互很别扭。本项目最核心的场景是单向的输入定位用 runJavaScript 就足够了。把这条主流程走通以后反向交互再扩展也不迟。2. Ubuntu 环境准备与百度地图 AK 申请2.1 QWebEngine 模块安装与验证用官方在线安装器装 QT 的朋友最容易踩坑基础组件选完之后WebEngine 是单独的模块必须手动勾选 Qt WebEngine否则编译的时候#include QWebEngineView直接报找不到头文件。走 apt 安装路线在 Ubuntu 20.04/22.04 上执行sudo apt update sudo apt install qtbase5-dev qtwebengine5-dev装完想验证模块是否存在直接建一个空 QWebEngineView 工程编译一次最可靠。如果系统里同时装了 apt 版和官网版 QT环境变量容易打架出现莫名其妙的链接错误时先执行which qmake看当前用的到底是哪一套。2.2 AK 申请与 Referer 白名单配置百度地图开放平台注册登录后在“应用管理 - 创建应用”里填应用名称应用类型选“浏览器端”。创建页有一个极其关键的选项叫 Referer 白名单本地调试阶段直接填*放通所有来源。很多人在这一步填了 localhost 或者域名结果程序一加载地图就报 200 错误Referer 不合法。原因在于 qrc:// 或 file:// 协议加载本地 HTML 时Chromium 带过去的 Referer 要么为空要么是qrc:///resources/map.html这种非标准 scheme百度后端匹配不上你填的域名。注意无论 HTML 放在本地文件还是 qrc 里本地调试阶段 AK 的 Referer 白名单都填*等上线部署到服务器再改成真实域名。拿到 AK 后替换进 HTML 里的 script src 即可script typetext/javascript srchttps://api.map.baidu.com/api?v3.0ak你的AK/script3. 核心实现地图 HTML 与 QT 工程的完整对接3.1 地图 HTML 编写要点map.html 的完整代码放下面核心是定义一个全局的 locate 函数外部才能用window.locate()调到!DOCTYPE html html langzh-CN head meta charsetutf-8 title百度地图定位页/title style html, body { margin: 0; padding: 0; width: 100%; height: 100%; } #map-container { width: 100%; height: 100%; } /style script typetext/javascript srchttps://api.map.baidu.com/api?v3.0ak你的AK/script /head body div idmap-container/div script var map null; function initMap() { map new BMap.Map(map-container); map.centerAndZoom(new BMap.Point(116.403873, 39.914889), 15); map.enableScrollWheelZoom(true); map.addControl(new BMap.NavigationControl()); map.addControl(new BMap.ScaleControl()); } function doLocate(lng, lat) { var point new BMap.Point(lng, lat); map.centerAndZoom(point, 17); map.clearOverlays(); var marker new BMap.Marker(point); map.addOverlay(marker); var infoWindow new BMap.InfoWindow( 经度: lng br纬度: lat, { width: 220, title: 定位坐标 } ); marker.addEventListener(click, function () { map.openInfoWindow(infoWindow, point); }); } function locate(lng, lat) { if (!map) { console.error(地图尚未初始化); return; } doLocate(parseFloat(lng), parseFloat(lat)); } window.onload initMap; /script /body /html几个细节必须提醒定位函数必须写在全局作用域里模块方式导出的函数 C 侧不一定拿得到。BMap.Point 构造函数接收的是数字lng、lat 进来后做一次 parseFloat 兜底避免传字符串在部分版本里出问题。每次定位前先 clearOverlays()否则上一个标记还留在图上视觉上很乱。InfoWindow 里的内容用字符串拼接就能显示坐标不用搞复杂模板。3.2 QT 工程代码与资源文件新建一个 Widgets 工程pro 文件长这样QT core gui webenginewidgets greaterThan(QT_MAJOR_VERSION, 4): QT widgets TARGET map_demo TEMPLATE app SOURCES main.cpp RESOURCES resources.qrc用 qrc 资源把 HTML 打进二进制运行时永远能找到页面不受工作目录影响。qrc 文件RCC qresource prefix/ fileresources/map.html/file /qresource /RCCmain.cpp 的完整代码#include QApplication #include QWebEngineView #include QLineEdit #include QPushButton #include QVBoxLayout #include QHBoxLayout #include QLabel #include QWidget #include QUrl #include QDebug #include cmath int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.setWindowTitle(QT 调用百度地图 - 经纬度定位); window.resize(1000, 700); QWebEngineView *view new QWebEngineView(window); view-setUrl(QUrl(qrc:/resources/map.html)); view-setContextMenuPolicy(Qt::NoContextMenu); QLabel *lngLabel new QLabel(经度:, window); QLineEdit *lngEdit new QLineEdit(116.403873, window); QLabel *latLabel new QLabel(纬度:, window); QLineEdit *latEdit new QLineEdit(39.914889, window); QPushButton *locateButton new QPushButton(定位, window); locateButton-setEnabled(false); QHBoxLayout *toolLayout new QHBoxLayout; toolLayout-addWidget(lngLabel); toolLayout-addWidget(lngEdit); toolLayout-addWidget(latLabel); toolLayout-addWidget(latEdit); toolLayout-addWidget(locateButton); toolLayout-addStretch(); QVBoxLayout *mainLayout new QVBoxLayout(window); mainLayout-addWidget(view, 1); mainLayout-addLayout(toolLayout); QObject::connect(view, QWebEngineView::loadFinished, [](bool ok) { if (ok) { locateButton-setEnabled(true); } }); QObject::connect(locateButton, QPushButton::clicked, []() { bool okLng false; bool okLat false; double lng lngEdit-text().trimmed().toDouble(okLng); double lat latEdit-text().trimmed().toDouble(okLat); if (!okLng || !okLat || std::abs(lng) 180 || std::abs(lat) 90) { qDebug() 经纬度不合法; return; } QString js QString(window.locate(%1, %2);).arg(lng).arg(lat); view-page()-runJavaScript(js); }); window.show(); return app.exec(); }代码里已经处理了几个隐性坑定位按钮初始禁用等 loadFinished 信号确认页面加载完成再启用经纬度做了范围和格式校验runJavaScript 拼串时用%1、%2直接填充 double不会出现千分位分隔符之类的问题。3.3 编译运行与效果验证mkdir build cd build qmake ../map_demo.pro make ./map_demo正常启动后界面上面是地图下边一条经度、纬度输入框和定位按钮。改输入框里的数值点击定位地图会跳到对应位置并落下标记点点击标记出现带坐标的弹窗。到这里核心需求就算跑通了下面两个优化点强烈建议一起做。4. 定位交互优化与坐标偏移处理4.1 通过 loadFinished 控制定位按钮前面 main.cpp 里已经用了 loadFinished 控制按钮页面没加载完就置灰加载完成才允许点击。这种做法可以避免用户一启动就点定位而此时 HTML 里的 locate 函数还不存在runJavaScript 调用会静默失败控制台也没有明显报错。另外还有一个细节百度地图 JS API 是外部脚本网络慢的时候 loadFinished 会相应延迟。所以在 HTML 里保留if (!map)判空双保险。程序里能容忍的最长等待时间按实际网络情况评估内网和公网差别很大没有统一标准。4.2 坐标系不一致导致定位偏移这是最容易忽略的“伪 Bug”。如果你手里的经纬度来自 GPS 设备或手机定位导出的数据大概率是 WGS84 坐标系而百度地图内部用的是 BD09两者在城市尺度上能差出几百米定位点肉眼可见地偏。解决办法是进百度地图前做坐标转换。前端最省事的是用 BMap.Convertorfunction locateWithConvert(lng, lat) { var convertor new BMap.Convertor(); var points [new BMap.Point(lng, lat)]; convertor.translate(points, 1, function (data) { if (data.status 0) { var p data.points[0]; doLocate(p.lng, p.lat); } }); }translate 的第二个参数 1 表示原始坐标是 WGS84回调里拿到的就是 BD09 坐标。如果确定输入本来就是百度坐标直接走 locate 反而更快。C 侧也能处理转换但既然前端有能力少一层网络请求和 C 代码总是好的。4.3 点击地图回传坐标QWebChannel 扩展需求一旦变成“在地图上点一下把坐标填回输入框”单向的 runJavaScript 就不够用了。这时候启动 QWebChannelC 侧注册一个 QObject 到 channelHTML 里通过 qt.webChannelTransport 拿到这个对象在地图 click 事件里调用 C 槽函数。代码结构不复杂但建议把 C 侧的回调对象单独抽成一个 Bridge 类槽函数写在里面避免 main.cpp 越来越臃肿。这个扩展方向后期可以做一篇独立文章核心思路就是“反向通信”。5. 白屏、JS 无响应等典型问题排查5.1 问题速查表现象可能原因解决办法程序启动后地图区域一片白Chromium 沙箱或显卡驱动问题设置QTWEBENGINE_CHROMIUM_FLAGS--no-sandbox必要时加--disable-gpu页面加载但地图不显示AK 无效或 Referer 不匹配核对 AK白名单填*再试点击定位没反应HTML 未加载完locate 不存在loadFinished 信号控制按钮状态标记与实际地点偏差几百米坐标系不一致用 BMap.Convertor 或 geoconv 接口转换qrc 修改后页面不更新编译缓存删除 build 目录重新 qmakerunJavaScript 报解析错误经纬度里混入非法字符toDouble 校验后再拼接 JS5.2 远程调试网页与 root 环境处理QWebEngineView 内置了 Chromium可以开远程调试端口看网页 console。运行前设置环境变量QTWEBENGINE_REMOTE_DEBUGGING9222启动后用 Chrome 打开localhost:9222就能像调试普通网页一样看 console、检查元素、手动执行 JS。定位函数失效时到底是 BMap is not defined 还是 locate is not defined一眼就能分清。再说一个 Ubuntu 下非常常见的坑在虚拟机或服务器上用 root 用户跑程序Chromium 默认禁止沙箱窗口直接白屏。解决办法是启动前加上export QTWEBENGINE_CHROMIUM_FLAGS--no-sandbox --disable-gpu ./map_demo虚拟机没装显卡驱动时还可以再配合export LIBGL_ALWAYS_SOFTWARE1强制 Mesa 软件渲染白屏问题基本都能解决。6. 扩展玩法与经验心得6.1 打包发布注意事项发布时 WebEngine 依赖的资源文件qtwebengine_resources.pak、icudtl.dat 等必须和可执行文件放一起推荐用 linuxdeployqt 自动收集。百度地图 JS API 依赖外网离线环境跑不起来除非换离线瓦片方案或者对接公司内部的瓦片服务这一点要在需求阶段就跟产品确认好。另一个小事项如果 HTML 用 qrc 方式打包进了二进制AK 的 Referer 白名单建议在生产环境配成实际访问域名而不是继续用*。开发期无所谓上线后还是要收紧安全边界。6.2 我踩过坑后的几条心得先把 HTML 独立在浏览器里调通再塞进 QT。我见过太多人把两步揉在一起出了 bug 分不清是 C 的问题还是网页的问题。先在 Chrome 里打开 map.html能看到地图、能手动调 locate确认无误后再进工程排查范围一下子就缩小了。AK 不要硬编码提交到公共仓库泄露出去被别人盗用账号额度会被刷爆轻则限流重则封禁。正式系统里用配置文件或者环境变量注入这个习惯要趁早养。定位 marker 建议用一个全局变量保存引用后面更新 InfoWindow 或者做轨迹绘制时有据可查。地图默认控件自带缩放按钮但滚动缩放在桌面端体验更好HTML 里已经开了 enableScrollWheelZoom这个开关在初版代码里经常会漏漏掉之后用户会以为地图卡死了排查起来又容易忽略写的时候要当个必选项记着。本文还有配套的精品资源点击获取

相关新闻

LFW人脸数据集lfw_home.zip拆解:目录结构、加载与实战

LFW人脸数据集lfw_home.zip拆解:目录结构、加载与实战

2026/9/8 1:42:34

简介:这是面向人脸识别研究者与深度学习初学者的经典数据集资源,围绕 LFW 基准整理而成,用于人脸验证、辨识算法训练与性能对比。压缩包内共 9 个文件,主要包含图像归档、配对标注文件、Python 序列化数据与辅助脚本:其…

阿里云Token计划:统一API调用多AI模型实践指南

阿里云Token计划:统一API调用多AI模型实践指南

2026/9/8 1:42:34

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

小布Next AI助手开发实战:端云协同与情景感知技术详解

小布Next AI助手开发实战:端云协同与情景感知技术详解

2026/9/8 1:42:34

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

Ansys Maxwell参数设置详解:电流激励有效值/幅值与边界条件

Ansys Maxwell参数设置详解:电流激励有效值/幅值与边界条件

2026/9/8 3:52:40

如果你是因为“Maxwell参数”这个词点进来的,那大概率遇到过这种场面:Ansys Maxwell的GUI打开了,模型也画好了,结果在设置激励、材料、边界条件时,总有几个参数不知道填什么,或者填完以后算出来的结果完全对…

TMS320F28035 eCAN主从通信调试:回环模式为何不能替代总线互测

TMS320F28035 eCAN主从通信调试:回环模式为何不能替代总线互测

2026/9/8 3:52:40

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

期末博客作业写作指南:从选题到发布全流程

期末博客作业写作指南:从选题到发布全流程

2026/9/8 3:52:40

每到期末,社交媒体和课程群里就会被同一个问题刷屏:“期末博客作业到底怎么写?”“老师让我们交一篇博客,可我不知道写什么,也不知道写成什么样才能拿高分。” 这篇博文就是来帮你解决这件事的。我会从选题、结构、写…

嵌入式启动代码与内存布局:data段、bss段、XIP及位置无关码深度解析

嵌入式启动代码与内存布局:data段、bss段、XIP及位置无关码深度解析

2026/9/8 3:52:40

做嵌入式开发,几乎人人都要过这么一关:第一次打开启动文件(startup_xxx.s),看到里面有几十行汇编——设置栈指针、调用 SystemInit、把一段数据从 Flash 复制到 RAM、再把一片区域清零。注释写得很简单:Cop…

Rocky Linux下QEMU Guest Agent无法获取IP?四层链路排查指南

Rocky Linux下QEMU Guest Agent无法获取IP?四层链路排查指南

2026/9/8 3:52:40

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

opencode 完全指南:AI 编程助手的模型自由与 Skills 扩展实战

opencode 完全指南:AI 编程助手的模型自由与 Skills 扩展实战

2026/9/8 3:42:39

最近这段时间,AI编程助手圈子里冒出来一个热度非常高的新工具叫 opencode,我在几个实际项目里用它顶替了以前顺手但越来越贵的 Claude Code 工作流,整体体验相当能打。如果说 Claude Code 是“能用”,那 opencode 给我的感觉就是“…

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/7 20:21:46

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/7 3:44:24

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/7 8:03:37

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

芯片良率波动可视化:动画拆解工艺因果,重建客户信任

芯片良率波动可视化:动画拆解工艺因果,重建客户信任

2026/9/8 0:02:30

芯片这个行业有个不太被人摆到台面上、但几乎每天都在发生的场景:客户拿着一条良率曲线截图问你,这批货的良率怎么掉了三个点,是不是工艺出问题了,产生的不良会不会流到他们产线上去。你解释了半天,客户似懂非懂&#…

PyTorch DataLoader参数冲突:sampler与shuffle互斥的根源与正确写法

PyTorch DataLoader参数冲突:sampler与shuffle互斥的根源与正确写法

2026/9/8 0:02:30

ValueError: sampler option is mutually exclusive with shuffle,这个报错我在 PyTorch 的 DataLoader 上至少见过几十次了,而且很有意思的是,它经常不是新手专属——很多写了好几年模型的老手,在从单机改成自定义采样器&#xf…

中国车企再破谣言,GAC吉利零跑获欧盟安全五星

中国车企再破谣言,GAC吉利零跑获欧盟安全五星

2026/9/8 0:02:30

有人可能在网上开着皮卡拍视频,声称中国电动车不仅性能不如美国大排量车型,安全性也堪忧。然而事实恰恰相反,GAC、吉利和零跑最新推出的电动车型在极为严苛的欧盟新车安全评鉴(Euro NCAP)测试中全部斩获满分。就在特斯…

远程协作的工作台整理

远程协作的工作台整理

2026/9/7 3:38:07

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/8 3:19:39

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/8 4:00:23

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…