当前位置: 首页 > news >正文

Qt加载百度地图详细流程(附带报错解决方法)

作者:求一个demo

版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

内容通俗易懂,废话不多说,我们直接开始------>>>>>>

!!!!!!成果展示!!!!!!

一、创建一个Qt工程(QWidget/QMainWindow均可)

我的Qt环境:Qt是5.14.2,Qt Creator是4.11.1。

(此处以创建QMainWindow为例)

二、在百度地图开发者平台获取密钥

1、首先在“百度地图开放平台”注册一个账号,链接:百度地图-百万开发者首选的地图服务商,提供专属的行业解决方案

2、选择控制台

3、点击“应用管理”—“我的应用”—“创建应用”。

4、应用类型一定要选择“浏览器端”,Referer白名单的话,如果自己没有专门的需求,填一个星号*就行,然后保存自己的AK。

三、创建网页html,并放在相应位置

此处博主创建名为“index.html”的文件,代码如下:

<!DOCTYPE html>
<html>
<head><meta name="viewport" content="initial-scale=1.0, user-scalable=no" /><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>BDMap Sample</title><style type="text/css">html{height:100%}body{height:100%;margin:0px;padding:0px}#container{height:100%} /* 确保地图容器占满QWebEngineView */</style><!-- 1. 加载百度地图 JS API v3(非WebGL,兼容性更好) --><script type="text/javascript" src="https://api.map.baidu.com/api?v=3.0&ak=tSE1tEJjbMzrknZMAQgoj5A"></script><!-- 2. 加载QWebChannel(使用qrc资源路径,避免绝对路径问题) --><script type="text/javascript" src="qrc:/qtchannel/qwebchannel.js"></script>
</head>
<body><div id="container"></div><script type="text/javascript">// 3. 先初始化QWebChannel,再初始化地图(确保交互通道就绪)var JSInterface = null;new QWebChannel(qt.webChannelTransport, function(channel) {JSInterface = channel.objects.JSInterface; // 获取Qt注册的交互对象JSInterface.logFromJS("QWebChannel初始化成功"); // 通知Qt交互就绪// 4. QWebChannel就绪后,再初始化百度地图(避免阻塞)initBaiduMap();});// 5. 百度地图初始化函数(独立封装,逻辑清晰)function initBaiduMap() {try {if (typeof BMap === 'undefined') {console && console.error && console.error('BMap 未加载,检查网络或AK');if (JSInterface && JSInterface.logFromJS) JSInterface.logFromJS('BMap 未加载,可能是网络或AK问题');return;}var map = new BMap.Map("container");// 沈阳浑南区默认坐标(作为定位失败的备选)var defaultPoint = new BMap.Point(123.431982, 41.766281);// 初始化地图(先显示默认位置)map.centerAndZoom(defaultPoint, 15);map.enableScrollWheelZoom(true);// IP定位获取当前位置var geolocation = new BMap.Geolocation();geolocation.getCurrentPosition(function(r) {if (this.getStatus() == BMAP_STATUS_SUCCESS) {// 定位成功,移动到当前位置var currentPoint = r.point;map.panTo(currentPoint);// 添加当前位置标注var marker = new BMap.Marker(currentPoint);map.addOverlay(marker);// 显示定位信息var infoWindow = new BMap.InfoWindow("当前位置:<br/>经度:" + currentPoint.lng + "<br/>纬度:" + currentPoint.lat,{width: 200, height: 100, title: "定位成功"});marker.addEventListener("click", function() {map.openInfoWindow(infoWindow, currentPoint);});JSInterface.logFromJS("定位成功:(" + currentPoint.lng + "," + currentPoint.lat + ")");} else {// 定位失败,使用默认坐标(沈阳浑南)JSInterface.logFromJS("定位失败,错误码:" + this.getStatus() + ",使用默认位置");var marker = new BMap.Marker(defaultPoint);map.addOverlay(marker);}}, {enableHighAccuracy: true}); // 启用高精度定位window.map = map; // 将地图实例挂载到window,供addMarker使用JSInterface.logFromJS("百度地图初始化成功");} catch (e) {JSInterface.logFromJS("地图初始化异常:" + e.message);}
}// 6. 简化addMarker函数(移除无意义的alert,避免阻塞)function addMarker(lng, lat) {if (!window.map) {JSInterface.logFromJS("addMarker失败:地图未初始化");return;}var newPoint = new BMap.Point(lng, lat);var newMarker = new BMap.Marker(newPoint);window.map.addOverlay(newMarker);JSInterface.logFromJS("添加标注成功:(" + lng + "," + lat + ")");}// 全局错误日志window.onerror = function(message, source, lineno, colno, error) {try {if (JSInterface && JSInterface.logFromJS) {JSInterface.logFromJS('JS错误: ' + message + ' @' + source + ':' + lineno + ':' + colno);}} catch (e) {}};</script>
</body>
</html>

下面截图将告诉html中哪些地方需要修改:

四、配置相关资源文件

1、首先,找到自己相关路径下的qwebchannel.js文件(例如我的路径是E:\perfect\qt5.14.2\Examples\Qt-5.14.2\webchannel\shared\qwebchannel.js),将其放到你的工程文件根目录(也就是你各个类代码文件的位置,如下图)。(释:qwebchannel.js能够让你的Qt工程和JS文件进行通信)。

2、为了方便管理工程的静态资源文件(qwebchannel.js),将其打包到可执行程序中(打包成qrc文件),避免程序运行时依赖外部文件路径,提高项目可移植性和稳定性。步骤如下:

3、在html文件中添加你的qrc资源文件路径,便于Qt和JS通信。

4、创建Qt中的ui,并进行相关配置。(释:将Widget控件提升为QWebEngineView,是因为QWebEngineView支持网页渲染与交互能力。它支持加载 HTML、JS、CSS,实现网页交互。)

5、别忘记在.pro文件中加入下面这段代码(释:目的是为了引入Qt WebEngine模块,让项目能使用QWebEngineView等网页相关的类。):

QT += webenginewidgets

五、编写Qt代码

项目结构如下:

1、MagImageProDisplay.pro代码如下:

QT       += core gui
QT += webenginewidgetsgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0# 交互类源文件
SOURCES += \jsinterface.cpp \main.cpp \mainwindow.cpp# 交互类头文件
HEADERS += \jsinterface.h \mainwindow.hFORMS += \mainwindow.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += targetRESOURCES += \qwebchannelresources.qrc

2、创建JSInterface类(JSInterface 是一个桥梁类,用于实现 C++ 与 JavaScript 之间的双向通信),代码中有详细注释。

(1)JSInterface.h如下:

#ifndef JSINTERFACE_H
#define JSINTERFACE_H
#include <QObject>
#include <QDebug>class JSInterface : public QObject
{Q_OBJECT
public:explicit JSInterface(QObject *parent = nullptr);// (可添加供HTML调用的方法,如后续扩展功能)
public slots:void logFromJS(const QString &msg) {qDebug() << "[HTML Log]:" << msg; // 接收HTML日志,辅助调试}
};#endif // JSINTERFACE_H/*
JSInterface 是一个桥梁类,用于实现 C++ 与 JavaScript 之间的双向通信:
1、让网页中的 JS 代码能够调用 C++ 方法;
2、处理从网页发送过来的数据或命令;
3、在 C++ 端对来自网页的数据进行安全验证;
4、执行需要在 C++ 端处理的核心功能。如果去掉此类,WebChannel失去意义:
QWebChannel 需要注册 QObject 才能工作,没有注册对象,WebChannel 就只是一个空通道。
*/

(2)JSInterface.cpp如下:

#include "JSInterface.h"JSInterface::JSInterface(QObject *parent) : QObject(parent)
{}

3、MainWindow类。

(1)MainWindow.h如下:

#ifndef MAINWINDOW_H // 防止头文件重复包含的宏定义
#define MAINWINDOW_H // 定义主窗口头文件宏#include <QMainWindow>
#include <QWidget>
#include <QWebEngineHistory> // 包含Web引擎历史记录类头文件
#include <QWebEngineHistoryItem>  // 包含Web引擎历史记录项类头文件
#include <QWebEnginePage>  // 包含Web引擎页面类头文件
#include <QWebEngineView>  // 包含Web引擎视图类头文件
#include <QtWebEngineWidgets/QtWebEngineWidgets>  // 包含Web引擎部件模块头文件QT_BEGIN_NAMESPACE // 开始Qt命名空间
namespace Ui { class MainWindow; }
QT_END_NAMESPACE // 结束Qt命名空间class MainWindow : public QMainWindow
{Q_OBJECT  // Qt元对象系统宏,支持信号槽机制public:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

(2)MainWindow.cpp如下:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "JSInterface.h"  // 包含JavaScript交互接口头文件
#include <QFile>  // 包含文件操作类头文件
#include <QUrl>  // 包含URL处理类头文件MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QWebEnginePage *page = ui->BaiduMap->page();  // 获取Web引擎视图的页面对象QWebEngineProfile *profile = page->profile();  // 获取页面配置文件(未使用)// 处理网页特性权限请求(地理位置等),自动授予当前页面的定位权限connect(page, &QWebEnginePage::featurePermissionRequested, this,[page](const QUrl &securityOrigin, QWebEnginePage::Feature feature) {if (feature == QWebEnginePage::Geolocation) {page->setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionGrantedByUser);}});// 启用跨域请求支持QWebEngineSettings *settings = page->settings();  // 获取页面设置对象settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);  // 允许本地内容访问远程URLsettings->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, true);  // 允许本地内容访问文件URLsettings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true);  // 允许运行不安全内容(混合内容)settings->setAttribute(QWebEngineSettings::WebGLEnabled, false);  // 关闭WebGL,避免显卡驱动导致崩溃settings->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled, false);  // 关闭2D加速// 初始化交互对象(独立于QWebEngineView),即 创建JavaScript交互接口对象JSInterface *jsInterface = new JSInterface(this);// 配置QWebChannel(必须在load之前完成)QWebChannel *webChannel = new QWebChannel(this);  // 创建Web通道对象webChannel->registerObject("JSInterface", jsInterface);  // 注册交互对象到Web通道,JavaScript中可通过此名称访问ui->BaiduMap->page()->setWebChannel(webChannel);  // 将Web通道设置到页面// 加载HTML(确保路径正确,使用QUrl::fromLocalFile避免路径解析错误)QString htmlPath = QCoreApplication::applicationDirPath() + "/html/index.html";  // 构建HTML文件路径QFile htmlFile(htmlPath); // 创建文件对象// 检查文件是否存在if (!htmlFile.exists()) {qDebug() << "[Error] HTML文件不存在:" << htmlPath;return;}QUrl htmlUrl = QUrl::fromLocalFile(htmlPath);  // 将文件路径转换为URLui->BaiduMap->page()->load(htmlUrl);  // 加载HTML文件qDebug() << "[Info] 加载HTML路径:" << htmlUrl.toString();  // 输出加载信息}MainWindow::~MainWindow()
{delete ui;
}

六、可能遇见的问题

按照上面的流程是不会出现下面这些问题的,因为博主就是解决了下面的问题才写出上面的流程和代码的,加上这章节内容只是为了记录一下,万一某天某刻某人遇到下面问题了呢!

问题一:可能出现下面图片报错。
解决:建议重新注册一个百度的api,因为KEY可能被删除了(可以去看第二章节如何获取密钥的)。

问题二:地图快要加载出来的时候,然后整个地图的ui闪退没了(下图)。
解决:检查一下HTML中QWebChannel与百度地图API的加载顺序,加载顺序不当会触发 Qt WebEngine 控件崩溃。所以一定要先确保QWebChannel通信通道初始化完成并注册好交互对象(JSInterface),避免页面JS运行时通道还没建好。

问题三:地图的内容一直加载不出来(如下图)

解决:保留地理位置自动授权(主要还是权限没有),(后面都是次要)将前端从 BMapGL 切换为 BMap v3(非 WebGL),避免显卡驱动/QtWebEngine WebGL 崩溃。

最后,如有不足和错误的地方,期待私信指正!


文章转载自:

http://bbKYkGRH.yrngx.cn
http://QgdVYSht.yrngx.cn
http://KkCuWaPi.yrngx.cn
http://uP0oVezJ.yrngx.cn
http://NRKqzxMz.yrngx.cn
http://g4BpByjq.yrngx.cn
http://CBwXfDY7.yrngx.cn
http://WwwEehRY.yrngx.cn
http://VSH5wr8c.yrngx.cn
http://rfjYJfRf.yrngx.cn
http://WDEHhQjo.yrngx.cn
http://OyParQK0.yrngx.cn
http://CyoWEIja.yrngx.cn
http://ZGvUNkFG.yrngx.cn
http://9fYGmleG.yrngx.cn
http://Dt94M90b.yrngx.cn
http://Ru0bbc0x.yrngx.cn
http://T41VKso9.yrngx.cn
http://bre5eduk.yrngx.cn
http://H5iHxBlj.yrngx.cn
http://le7YyeD0.yrngx.cn
http://l76ME7wa.yrngx.cn
http://gT5ad7ln.yrngx.cn
http://wi2Hyc4o.yrngx.cn
http://wUbGMoto.yrngx.cn
http://w10HXXTE.yrngx.cn
http://iCuPMCwI.yrngx.cn
http://p0GxkBgY.yrngx.cn
http://V4x8glQt.yrngx.cn
http://nRQymK0g.yrngx.cn
http://www.dtcms.com/a/379224.html

相关文章:

  • 3D渲染时GPU内存不足解决措施
  • MySQL什么操作会加锁?
  • 中州养老:华为云设备管理接口开发全流程
  • 探讨图片以Base64存数据库的合理性
  • MoonBit 再次走进清华:张宏波受邀参加「思源计划」与「程序设计训练课」
  • RabbitMQ如何实现消息的持久化?
  • Crawlergo安装全流程
  • 完全背包问题 - 动态规划最优解法(Java实现)
  • 如何选择合适的双轴倾角传感器厂家提升水平监测准确性?
  • 洛谷PP5318 查找文献 (深度搜索与广度搜索)详解
  • 手机云服务是什么意思?
  • Linux 基础操作全攻略:从文件解压到服务器管理
  • web:ts的类类型
  • 初识StarRocks
  • linux常见的基础命令及其作用
  • 12 Prompt 模板化与参数化
  • 自动化车间无线安灯呼叫系统解决方案
  • Oracle APEX 如何运行页面时跳过登录页
  • list容器
  • Docker Compose:轻松管理多容器应用
  • 云蝠智能大模型呼叫新模型上线,拥抱AGI
  • 网站SEO内部优化一般包括哪些内容和方法
  • 18j621-3通风天窗图集pdf(免费高清版)
  • 以下是UniApp启动速度优化的深度方案
  • GoogLeNet实战:用PyTorch实现经典Inception模块
  • verilog中task的使用
  • SpringDoc OpenAPI集成spring boot3
  • 安卓13_ROM修改定制化-----安卓 13 系统 ROM 定制化与低版本系统的核心区别
  • yolo学习笔记02——yolo简介
  • OpenCV 开发 -- 图像算术运算