【QT--使用百度地图API显示地图并绘制路线】

news2024/12/26 11:03:40

QT--使用百度地图API显示地图并绘制路线

  • 前言
  • 准备工作
    • 申请百度地图密钥(AK)
    • 安装开发环境
  • 开发过程
    • 新建项目
    • ui界面
    • GPSManager类
    • 主窗口
    • Map
  • 效果展示

前言

先吐槽一下下,本身qt学的就不咋滴,谁想到第一件事就是让写一个上位机工具,根据CAN总线传来的位置信息,在地图上去绘制路线,并获取当前路段的限速信息等。当听到这个需求的时候,第一时间是有点懵逼的。自己原本是没接触过这方面的知识,而且qt学的也特别的垃圾,但是以我的性格还是答应了下来。最终也是花了几天的时间做了出来。通过做这个简单的小工具,自己也学到了还能多。接下来我就简单说一说如何使用百度地图API来显示地图并根据位置信息绘制路线这一功能。其他的就不方便说了。

准备工作

申请百度地图密钥(AK)

在使用百度地图之前,我们需要拥有一个自己的百度账号,申请注册成为百度开发者,然后我们需要创建一个浏览器端应用,就可以获取到一个唯一的服务秘钥(AK)
具体的步骤小伙伴们可以去看一些其他博主的文章,这里我就不详细的去说了。

安装开发环境

说到开发环境,这里我踩了很多的坑啊,这里我来强调一下。
首先我的qt版本是5.14.2,在安装QT的时候一定把MSVC2017给选上!!!不然后面写代码导入模块时会出错的。
还有就是一定要安装一个Visual Studio 2017,因为我QT上是MSVC2017,所以这里我安装的是Visual Studio 2017。
如果环境搞得差不多了,就可以进行下面的开发了。

开发过程

新建项目

打开QT新建一个Application,在Kits页面将MSVC2017勾选上,如下图:
在这里插入图片描述
新建完成后,打开.pro文件添加如下代码:

QT +=webenginewidgets

重新构建一下项目,如果出现错误,请检查前面的开发环境。

ui界面

在这里插入图片描述
其中包括三个QLabel用来显示信息,分别是GPS信息,Speed信息,和绘制情况信息,一个按钮,来触发绘制,还有一个webEngineView,这个需要在Designer下拖拽上去。

GPSManager类

一、gpsmanager.h

#ifndef GPSMANAGER_H
#define GPSMANAGER_H
#include <QObject>
#include <QWebEngineView>
class GPSManager : public QObject
{
    Q_OBJECT

public:
    explicit GPSManager(QObject *parent = nullptr);

signals:
    void routeDrawn();
    void speedLimitReceived(int limit);
    void gpsUpdated(double latitude, double longitude);

public slots:
    void drawRoute(QWebEnginePage *webPage);
    void setGPSLocation(double latitude, double longitude);
public:
    int getSpeedLimit(double latitude, double longitude);
private:
    double currentLatitude;
    double currentLongitude;

};
#endif // GPSMANAGER_H

这个类旨在处理Qt应用程序中与GPS相关的功能。它发射信号以通知应用程序其他部分有关路线绘制、速度限制更新和GPS坐标更改的信息,并提供槽和函数来执行这些操作。
二、gpsmanager.cpp
构造函数:

GPSManager::GPSManager(QObject *parent) : QObject(parent)
{
    currentLatitude = 0.0;
    currentLongitude = 0.0;
}

这是 GPSManager 类的构造函数。它初始化了 currentLatitude 和 currentLongitude 两个成员变量为0.0。

drawRoute 函数:

void GPSManager::drawRoute(QWebEnginePage *webPage)
{
    // 在这里触发在 HTML 页面中编写的 JavaScript 代码来绘制路线
    QString javascriptCode = QString("drawNewPoint(%1, %2);").arg(currentLatitude).arg(currentLongitude);

    if (webPage) {
        // 执行 JavaScript 代码
        webPage->runJavaScript(javascriptCode);
        qDebug() << javascriptCode << endl;
    }

    // 获取限速信息并触发信号
    int speedLimit = getSpeedLimit(currentLatitude, currentLongitude);
    emit speedLimitReceived(speedLimit);

    // 触发路线绘制完成的信号
    emit routeDrawn();
}

这个函数用于绘制路线。它构建一个包含纬度和经度信息的 JavaScript 代码字符串,然后通过 QWebEnginePage 对象的 runJavaScript 方法在 HTML 页面中执行该代码。接着,它调用 getSpeedLimit 函数获取速度限制信息,并通过 emit 发射 speedLimitReceived 信号,以及发射 routeDrawn 信号表示路线绘制完成。

setGPSLocation 函数

void GPSManager::setGPSLocation(double latitude, double longitude)
{
    // 设置 GPS 位置
    currentLatitude = latitude;
    currentLongitude = longitude;
    emit gpsUpdated(currentLatitude, currentLongitude);
    qDebug("setGPSLocation");
}

这个函数用于设置 GPS 的位置信息。它接受纬度和经度作为参数,并将这些值存储在 currentLatitude 和 currentLongitude 成员变量中。然后,它通过 emit 发射 gpsUpdated 信号表示 GPS 位置已更新。

getSpeedLimit 函数:

int GPSManager::getSpeedLimit(double latitude, double longitude)
{
    // 在这里查询限速信息,这是一个示例
    // 实际上,你需要与地图数据提供商的API进行交互来获取限速信息

    // 这里我们模拟返回一个随机的限速值作为示例
    int randomSpeedLimit = QRandomGenerator::global()->bounded(30, 110); // 生成30到109之间的随机数
    return randomSpeedLimit;
}

这个函数用于获取速度限制信息。它是一个示例函数,实际中你需要与地图数据提供商的API进行交互来获取真实的速度限制信息。在示例中,它返回一个随机的速度限制值,范围在30到109之间。

主窗口

一、mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWebEngineView>
#include <QtWebChannel>
#include "gpsmanager.h"
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    //QWebEngineView *mapView;
    GPSManager *gpsManager;
    QTimer *timer;
private slots:
    void onGpsUpdated(double latitude, double longitude);
    void onRouteDrawn();
    void onSpeedLimitReceived(int limit);
    void on_pushButton_clicked();
    void onTimerTimeout();
};
#endif // MAINWINDOW_H

这个头文件定义了 MainWindow 类,该类是 Qt C++ 应用程序的主窗口。它包含了一些成员变量,包括用户界面对象、GPS 管理器和定时器,以及一些用于处理信号和事件的槽函数。这些槽函数用于响应与 GPS 更新、路线绘制、速度限制等相关的事件。
二、mainwindow.cpp
构造函数:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 创建GPSManager对象
    gpsManager = new GPSManager(this);
    // 连接GPSManager的信号与MainWindow的槽函数
    connect(gpsManager, &GPSManager::gpsUpdated, this, &MainWindow::onGpsUpdated);
    connect(gpsManager, &GPSManager::routeDrawn, this, &MainWindow::onRouteDrawn);
    connect(gpsManager, &GPSManager::speedLimitReceived, this, &MainWindow::onSpeedLimitReceived);
    ui->webEngineView->setUrl(QUrl("D:/QtCode/Google/map.html"));
    timer = new QTimer(this);
    timer->setInterval(5000);
}

这是 MainWindow 类的构造函数。在其中,进行了如下操作:
初始化用户界面 (ui->setupUi(this))。
创建 GPSManager 对象,用于处理 GPS 相关的操作。
连接 GPSManager 的信号与 MainWindow 的槽函数,以便在 GPS 更新、路线绘制和速度限制接收时执行相应操作。
设置 QWebEngineView 显示的网页 URL。
创建一个定时器 timer,并设置其定时间隔为 5000 毫秒(5秒)。

析构函数:

MainWindow::~MainWindow()
{
    delete ui;
    delete gpsManager;
    delete timer; // 释放定时器对象
}

这是 MainWindow 类的析构函数,用于释放动态分配的对象,包括用户界面对象 (ui)、GPSManager 对象和定时器对象。

槽函数 onGpsUpdated:

void MainWindow::onGpsUpdated(double longitude, double latitude)
{
    // 在这里可以更新UI以显示当前GPS坐标
    // 例如,更新UI的标签或其他元素
    qDebug("onGpsUpdated");
    ui->gps->setText(QString::number(longitude, 'f', 10) + " " + QString::number(latitude, 'f', 10));
}
这个槽函数用于处理 GPS 更新事件,更新用户界面上显示的 GPS 坐标信息。

槽函数 onRouteDrawn:

void MainWindow::onRouteDrawn()
{
    // 在这里可以执行与路线绘制相关的操作
    // 例如,显示路线的标签或其他元素
    ui->route->setText("正在绘制路线...");
}

这个槽函数用于处理路线绘制完成事件,更新用户界面上显示的信息。

槽函数 onSpeedLimitReceived:

void MainWindow::onSpeedLimitReceived(int limit)
{
    // 在这里可以更新UI以显示限速信息
    // 例如,显示限速信息的标签或其他元素
    ui->speed->setText("Speed Limit:" + QString::number(limit));
}

这个槽函数用于处理速度限制接收事件,更新用户界面上显示的限速信息。

槽函数 on_pushButton_clicked:

void MainWindow::on_pushButton_clicked()
{
    if (ui->pushButton->text() == "绘制") {
        connect(timer, &QTimer::timeout, this, &MainWindow::onTimerTimeout);
        timer->start();
        ui->pushButton->setText("取消绘制");
    } else {
        ui->pushButton->setText("绘制");
        timer->stop();
        ui->route->setText("");
    }
}

这个槽函数用于处理按钮点击事件。如果按钮上的文本是 “绘制”,则连接定时器的超时信号到 onTimerTimeout 槽函数,并启动定时器以触发路线绘制。如果按钮上的文本是 “取消绘制”,则停止定时器并重置界面上显示的路线信息。

槽函数 onTimerTimeout:

void MainWindow::onTimerTimeout()
{
    // 在定时器槽函数中调用gpsManager的函数
    lng = lng - 0.0003;
    lat = lat - 0.0003;
    gpsManager->setGPSLocation(lng, lat);
    gpsManager->drawRoute(ui->webEngineView->page());
    qDebug("%.10f %.10f", lng, lat);
}

这个槽函数用于处理定时器超时事件。在超时时,它调用 gpsManager 的函数来模拟 GPS 位置的变化,并触发路线绘制。在示例中,lng 和 lat 分别减小了0.0003,表示模拟GPS位置的移动。

Map

map.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>运输轨迹图</title>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=key"></script>
</head>
<body>
<div style="width:100%; height:100vh; border:1px solid gray" id="container"></div>

<script type="text/javascript">
    var map; // 保存地图对象
    var polyline; // 保存绘制的路线
    var points = []; // 保存所有点坐标

    // 创建地图函数
    function createMap() {
        // 如果地图对象不存在,创建地图
        map = new BMap.Map("container");
        map.centerAndZoom(new BMap.Point(116.404, 39.915), 13);
        map.addControl(new BMap.NavigationControl());               // 添加平移缩放控件
        map.addControl(new BMap.ScaleControl());                    // 添加比例尺控件
        map.addControl(new BMap.OverviewMapControl());              // 添加缩略地图控件
        map.enableScrollWheelZoom(true);
        // 初始化地图大小
        resizeMap();
        // 监听窗口大小变化事件,以动态调整地图大小
        window.addEventListener("resize", resizeMap);
    }

    // 初始化地图
    createMap();

    // 定义绘制路线的函数
    function drawRoute() {
        // 生成坐标点
        var trackPoint = [];
        for (var i = 0; i < points.length; i++) {
            trackPoint.push(new BMap.Point(points[i].lng, points[i].lat));
        }

        // 如果路线已存在,先清除
        //if (polyline) {
        //    map.removeOverlay(polyline);
        //}

        // 创建路线
        polyline = new BMap.Polyline(trackPoint, {strokeColor:"green", strokeWeight:6, strokeOpacity:1});
        map.addOverlay(polyline);
    }

    // 定义绘制新点的函数
    function drawNewPoint(lng, lat) {
        // 添加新的点坐标到 points 数组中
        var newPoint = { lng: lng, lat: lat };
        points.push(newPoint);

        // 如果超过最大长度,删除最早的点坐标
        if (points.length > 10) {
            points.splice(0, points.length - 10);
        }

        // 调用绘制路线函数以绘制新的路线
        drawRoute();
        // 获取最后一个点的坐标
            var lastPoint = new BMap.Point(lng, lat);

            // 计算地图视野以包含整个路线
            var view = map.getViewport(points);

            // 调整视野以确保最后一个点在地图中央
            var centerPoint = view.center;
            map.centerAndZoom(centerPoint, view.zoom);
            map.setCenter(lastPoint);
    }

    // 自适应地图大小
    function resizeMap() {
        var container = document.getElementById("container");
        var viewportWidth = window.innerWidth || document.documentElement.clientWidth;
        var viewportHeight = window.innerHeight || document.documentElement.clientHeight;
        container.style.width = viewportWidth + "px";
        container.style.height = viewportHeight + "px";
        map.setViewport();
    }
</script>
</body>
</html>

效果展示

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1021940.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OJ练习第177题——打家劫舍 IV(二分查找)

打家劫舍 IV 力扣链接&#xff1a;2560. 打家劫舍 IV 题目描述 沿街有一排连续的房屋。每间房屋内都藏有一定的现金。现在有一位小偷计划从这些房屋中窃取现金。 由于相邻的房屋装有相互连通的防盗系统&#xff0c;所以小偷 不会窃取相邻的房屋 。 小偷的 窃取能力 定义为…

人脸修复祛马赛克算法CodeFormer——C++与Python模型部署

一、人脸修复算法 1.算法简介 CodeFormer是一种基于AI技术深度学习的人脸复原模型&#xff0c;由南洋理工大学和商汤科技联合研究中心联合开发&#xff0c;它能够接收模糊或马赛克图像作为输入&#xff0c;并生成更清晰的原始图像。算法源码地址&#xff1a;https://github.c…

同步 -- 互斥锁

本篇文章基于Linux-6.5源码 建议&#xff1a;搭配Linux源码观看更佳 struct mutex {atomic_long_t owner;spinlock_t wait_lock; //自旋锁&#xff0c;该自旋锁的作用是保护后面的等待队列的原子性struct list_head wait_list; //等待队列 }; API接口 mutex_init 互斥锁初…

C语言入门Day_22 初识指针

目录 前言&#xff1a; 1.内存地址 2.指针的定义 3.指针的使用 4.易错点 5.思维导图 前言&#xff1a; 之前我们学过变量可以用来存储数据&#xff0c;就像一个盒子里面可以放不同的球一样。 这是一个方便大家理解专业概念的比喻。 在计算机世界里面&#xff0c;数据实…

海外ASO优化之提高应用曝光度的技巧1

作为应用程序的开发者&#xff0c;如何使我们的应用在众多竞争对手中脱颖而出&#xff1f;如何应用在App Store搜索中排名更高&#xff0c;以确保它符合App Store搜索中的搜索意图&#xff1f;这些都是我们要重点考虑的。 1、做好应用程序描述。 在填写应用描述之前&#xff0…

直线模组的常用语

在工业生产中&#xff0c;直线模组的叫法有很多种&#xff0c;对于新手小白来说&#xff0c;很容易就会被绕晕&#xff0c;今天我们就来简单说一下直线模组的常用称呼吧&#xff01; 1、直线模组&#xff1a;与直线滑台同义&#xff0c;基本可以相互互换。直线模组一般是指可以…

编译原理.龙书学习1

第一章&#xff1a; 编译器&#xff1a;将程序翻译成一种能够被计算机执行的形式 解释器&#xff1a;解释器直接利用用户提供的输入执行源程序中指定的操作 一个编译器的结构 编译器将源程序映射为语义上等价的目标程序&#xff0c;这个映射过程由两部分组成&#xff1a;分析…

ApiFox衔接前后端开发人员,提升沟通效率实践

1. 为什么不用Postman而要使用ApiFox 1.1. Postman的问题(不便) 多系统数据不互通 API设计者、前端开发、后端开发、测试人员大量重复工作。 效率低 可视化程度低、操作不友好。 无法团队协作 单机离线使用为主&#xff0c;成员之间无法实时同步数据&#xff0c;无法协作。 …

Unity实现简易太阳系

开发环境&#xff1a;Unity 2022.3.5f1c1 Visual Studio 2022 太阳系相关星体&#xff1a;太阳、八大行星、月球 模拟星系&#xff1a;太阳系、地月系 功能&#xff1a;支持行星以太阳为中心&#xff0c;任意轴进行公转&#xff0c;此处演示同一平面。 a1-a8为公转轴&#xff…

需要每日温习的java八股文基础

一、java &#xff08;1&#xff09;集合 1.list&#xff1a;LinkedList、ArrayList和Vector ArrayList、LinkedList和Vector的区别&#xff0c;场景和扩容机制源码 LinkedList 接口实现类&#xff0c; 链表&#xff0c; 插入删除&#xff0c; 没有同步&#xff0c; 线程不…

网站降权的康复办法(详解百度SEO数据分析)

随着搜索引擎算法的不断升级&#xff0c;很多网站在SEO优化过程中遭遇到降权的情况。如果您的网站也遭遇到了类似的问题&#xff0c;不必惊慌失措。本文将为您详细介绍网站降权恢复的方法&#xff0c;包括百度SEO数据分析、网站收录少的5个原因、网站被降权的6个因素以及百度SE…

什么是顶点颜色

在3D模型的渲染中&#xff0c;除了贴图属性外&#xff0c;顶点颜色也是一种常见的材质属性。顶点颜色是指通过给模型的顶点分配颜色值来定义模型表面的颜色。 顶点颜色通常以顶点数据的形式储存&#xff0c;并且与每个顶点的位置信息相对应。在渲染过程中&#xff0c;顶点颜色会…

【性能测试】JMeter:集合点,同步定时器的应用实例!

一、集合点的定义 在性能测试过程中&#xff0c;为了真实模拟多个用户同时进行操作以度量服务器的处理能力&#xff0c;可以考虑同步虚拟用户以便恰好在同一时刻执行操作或发送请求。 通过插入集合点可以较真实模拟多个用户并发操作。 (注意&#xff1a;虽然通过加入集合点可…

pdf在线加密怎么做?几个好用的方法分享

PDF在线加密怎么做&#xff1f;在进行PDF在线加密时&#xff0c;您可以使用以下几种方法来确保文档的安全性&#xff0c;并注意以下一些加密的注意事项。 方法一&#xff1a;使用PDF转换加密工具 首先我们可以在电脑上打开迅捷PDF转换器工具&#xff0c;进入该转换工具后先在顶…

Vue系列(二)之 基础语法【上篇】

目录 一. 插值 1.1 文本 1.2 原始HTML 1.3 属性 1.4 表达式 二. 指令 2.1 v-if/v-else-if/v-else指令 2.2 v-show指令 2.3 v-for指令 2.4 下拉框/复选框 2.5 动态参数 三. 过滤器 3.1 局部过滤器基本应用 3.2 局部过滤器串行使用 3.3 局部过滤器传参 3.4 全局过…

无涯教程-JavaScript - LCM函数

描述 LCM函数返回整数的最小公倍数。最小公倍数是最小的正整数,它是所有整数参数number1,number2等的倍数。使用LCM添加具有不同分母的分数。 语法 LCM (number1, [number2] ...)争论 Argument描述Required/OptionalNumber1, number2... 您想要最小公倍数的1到255个值。 如…

【JDK 8-函数式编程】4.2 BiFunction

一、BiFunction 二、改造上节课&#xff1a;四则运算 一、BiFunction Function 只能接收一个参数&#xff0c;要传递两个参数,则用 BiFunction 两个参数&#xff1a;可以是两种不同数据类型 调用方法: R apply(T t, U u); import java.util.Objects;/*** param <T>…

无涯教程-JavaScript - GCD函数

描述 GCD函数返回两个或多个整数的最大公约数。最大公约数是将number1和number2均除而无余数的最大整数。 语法 GCD (number1, [number2] ...)争论 Argument描述Required/OptionalNumber11 to 255 values. If any value is not an integer, it is truncated.Requirednumber…

颠覆传统!老子云支持70+三维格式转换,在线即可一键处理!

老子云自研AMRT展示框架及三维格式具有广泛兼容性&#xff0c;同时还会用户提供了3D格式在线转换工具&#xff0c;支持实现70三维格式模型的快速处理和转换。 你是不是也遇到过这种情况&#xff1a;做了半天的3D模型图&#xff0c;好不容易弄好了&#xff0c;到最后插入的时候居…

win11 腾讯会议提示未检测到可用麦克风

平时都用的耳机&#xff0c;今天直接用笔记本的音频进行会议&#xff0c;发现提示&#xff1a;显示未检测到可用麦克风&#xff0c;请插入设备重试&#xff1b;很奇怪的设置了腾讯会议的音频和电脑的&#xff0c;发现电脑的显示无可用的音频输入设备&#xff0c;折腾一番&#…