QGraphicsView实现简易地图10『自适应窗口大小』

news2024/12/23 16:48:17

前文链接:QGraphicsView实现简易地图9『层级缩放显示底图』
自适应窗口大小
当地图窗口放大或缩小的时候,需要地图能够动态覆盖整个视口。
1、动态演示效果
在这里插入图片描述

2、核心代码

注:WHMapView继承自MapView
void WHMapView::resize()
{
	if (m_curLevel >= 0)
		moveScene();
}

void MapView::moveScene()
{
	QString appPath = QApplication::applicationDirPath();
	QString dirPath = QString("%1/MapData/GaoDeMap/Map/MapPng/L0%2").arg(appPath).arg(m_curLevel + 1);
	// 视口宽度和高度
	int vw = viewport()->width();
	int vh = viewport()->height();

	// 计算呈现的瓦片地图左上角的场景坐标和视口坐标、呈现的瓦片地图右下角的场景坐标和视口坐标
	QPoint topLeftScenePos(m_topLeftTileCoord.x * PIXMAP_SIZE, m_topLeftTileCoord.y * PIXMAP_SIZE);
	QPointF topLeftViewPos = mapFromScene(topLeftScenePos);
	QPoint bottomRightScenePos(m_bottomRightTileCoord.x * PIXMAP_SIZE, m_bottomRightTileCoord.y * PIXMAP_SIZE);
	QPointF bottomRightViewPos = mapFromScene(bottomRightScenePos);

	int mapSideCount = pow(2, m_curLevel);

	if (MapUtility::sceneSize(m_curLevel) > vw)
	{
		// 1、水平瓦片坐标控制:判断最左侧瓦片是否完全进入视口、最右侧瓦片是否完全离开视口
		if (topLeftViewPos.x() > 0)
		{
			int count = qCeil(topLeftViewPos.x() / PIXMAP_SIZE);			// 左侧进入视口瓦片数量
			m_topLeftTileCoord.x = qMax(m_topLeftTileCoord.x - count, 0);	// 更新现左侧瓦片坐标X
		}

		if (bottomRightViewPos.x() > vw)
		{
			int count = qFloor((bottomRightViewPos.x() - vw) / PIXMAP_SIZE) + 1;	// 右侧离开视口瓦片数量
			m_bottomRightTileCoord.x = qMax(m_bottomRightTileCoord.x - count, 0);	// 更新现右侧瓦片坐标X
		}

		// 2、水平瓦片坐标控制:判断最右侧瓦片是否完全进入视口、最左侧瓦片是否完全离开视口
		if (bottomRightViewPos.x() + PIXMAP_SIZE < vw)
		{
			int count = qCeil((vw - (bottomRightViewPos.x() + PIXMAP_SIZE)) / PIXMAP_SIZE);			// 右侧进入视口瓦片数量
			m_bottomRightTileCoord.x = qMin(m_bottomRightTileCoord.x + count, mapSideCount - 1);	// 保存现右侧瓦片坐标X
		}

		if (topLeftViewPos.x() + PIXMAP_SIZE < 0)
		{
			int count = qFloor(fabs(topLeftViewPos.x()) / PIXMAP_SIZE);						// 左侧离开视口瓦片数量
			m_topLeftTileCoord.x = qMin(m_topLeftTileCoord.x + count, mapSideCount - 1);	// 保存现左侧瓦片坐标X
		}
	}

	if (MapUtility::sceneSize(m_curLevel) > vh)
	{
		// 3、垂直瓦片坐标控制:判断最上侧瓦片是否完全进入视口,最下侧瓦片是否完全离开视口
		if (topLeftViewPos.y() > 0)
		{
			int count = qCeil(topLeftViewPos.y() / PIXMAP_SIZE);			// 上侧进入视口瓦片数量
			m_topLeftTileCoord.y = qMax(m_topLeftTileCoord.y - count, 0);	// 保存现上侧瓦片坐标Y
		}

		if (bottomRightViewPos.y() > vh)
		{
			int count = qFloor((bottomRightViewPos.y() - vh) / PIXMAP_SIZE) + 1;	// 下侧离开视口瓦片数量
			m_bottomRightTileCoord.y = qMax(m_bottomRightTileCoord.y - count, 0);	// 保存现下侧瓦片坐标Y
		}

		// 4、垂直瓦片坐标控制:判断最下侧瓦片是否完全进入视口,最上侧瓦片是否完全离开视口
		if (bottomRightViewPos.y() + PIXMAP_SIZE < vh)
		{
			int count = qCeil((vh - (bottomRightViewPos.y() + PIXMAP_SIZE)) / PIXMAP_SIZE);			// 下侧进入视口瓦片数量
			m_bottomRightTileCoord.y = qMin(m_bottomRightTileCoord.y + count, mapSideCount - 1);	// 保存现下侧瓦片坐标Y
		}

		if (topLeftViewPos.y() + PIXMAP_SIZE < 0)
		{
			int count = qFloor(fabs(topLeftViewPos.y()) / PIXMAP_SIZE);						// 上侧离开视口瓦片数量
			m_topLeftTileCoord.y = qMin(m_topLeftTileCoord.y + count, mapSideCount - 1);	// 保存现上侧瓦片坐标Y
		}
	}

	// 获取移动前瓦片集合
	vector<TileCoord> vecOldTileCoord;
	for (int row = m_viewAndAroundTileRect.top(); row <= m_viewAndAroundTileRect.bottom(); ++row)
	{
		for (int col = m_viewAndAroundTileRect.left(); col <= m_viewAndAroundTileRect.right(); ++col)
		{
			vecOldTileCoord.push_back(TileCoord(col, row));
		}
	}

	// 获取移动后瓦片集合
	vector<TileCoord> vecNewTileCoord, vecAddTileCoord;
	m_viewAndAroundTileRect = CommonUtility::getViewAndAroundTileCoords(m_topLeftTileCoord.y, m_topLeftTileCoord.x, m_bottomRightTileCoord.y, m_bottomRightTileCoord.x, m_curLevel, vecNewTileCoord);
	for (const auto &tc : vecNewTileCoord)
	{
		// ①筛除已加载过的瓦片 ②线程加载存在滞后性,第二次移动时可能第一次m_tileItems还没有加载完毕,所以需要前一次范围作为过滤
		if (!m_tileItems.contains(tc) && std::find(vecOldTileCoord.begin(), vecOldTileCoord.end(), tc) == vecOldTileCoord.end())
		{
			vecAddTileCoord.push_back(tc);
		}
	}

	//showTileCoord();
	showGraticules();
	
	// 上方即为计算瓦片索引的核心代码,省略下方加载瓦片的代码...
	// 加载瓦片代码...
}

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

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

相关文章

Linux\_c输出

第一条Linux_c输出 初界面 : ls # 显示目录下的文件cd # 进入到某个目录 # 比如 我进入了Codels # 发现没有显示, 说明为文件下为空vim cpucdoe.c # 创建一个 .c的源码文件进入到了vim的编辑界面: i # 按i 就可以进行编辑 , 下面显示插入标识在编辑模式下, 可以通…

纯血鸿蒙APP实战开发——底部面板嵌套列表滑动案例

介绍 本示例主要介绍了利用panel实现底部面板内嵌套列表&#xff0c;分阶段滑动效果场景。 效果图预览 使用说明 点击底部“展开”&#xff0c;弹出panel面板。在panel半展开时&#xff0c;手指向上滑动panel高度充满页面&#xff0c;手指向下滑动panel隐藏。在panel完全展开…

netty 高性能架构设计--零拷贝

文章目录 前言一、直接内存1.1 什么是直接内存1.2 代码实现1.3 使用直接内存的优缺点 二、netty 零拷贝设计2.1 netty 直接内存2.2 netty 内存池 三、零拷贝的两种方式 前言 本篇从源码层面剖析 netty 高性能架构设计之零拷贝&#xff0c;并且扩展讲述零拷贝的两种实现方式。 …

免费在线录屏、无需注册、免费可用、无限制

免费在线工具 https://orcc.online/ 在线录屏 https://orcc.online/recorder pdf在线免费转word文档 https://orcc.online/pdf 时间戳转换 https://orcc.online/timestamp Base64 编码解码 https://orcc.online/base64 URL 编码解码 https://orcc.online/url Hash(MD5/SHA…

【C++STL详解(八)】--------stack和queue的模拟实现

目录 前言 一、stack模拟实现 二、queue的模拟实现 前言 前面也介绍了stack和queue的常见接口&#xff0c;我们也知道stack和queue实际上是一种容器适配器&#xff0c;它们只不过是对底层容器的接口进行封装而已&#xff0c;所以模拟实现起来比较简单&#xff01;一起来看看是…

FastDFS-单机扩容

描述 周一上班收到用户反馈系统异常&#xff0c;紧急排查日志发现报错&#xff1a;FdfsServerException:错误:28&#xff0c;错误信息:没有足够的存储空间。 解决 根据异常信息判断是文件服务器可用内存不够了&#xff0c;首先登录文件服务器&#xff0c;使用df -h命令查看一…

学习和分析各种数据结构所要掌握的一个重要知识——CPU的缓存利用率(命中率)

什么是CPU缓存利用率&#xff08;命中率&#xff09;&#xff0c;我们首先要把内存搞清楚。 硬盘是什么&#xff0c;内存是什么&#xff0c;高速缓存是什么&#xff0c;寄存器又是什么&#xff1f; 我们要储存数据就要运用到上面的东西。首先里面的硬盘是可以无电存储的&#…

VMware导入ova/ovf虚拟机文件

1.文件-打开-ova文件 2.为新虚拟机起名称 3.等待导入 4.导入完成&#xff0c;可以开始使用 参考链接&#xff1a;VMware导入ova/ovf虚拟机文件

C# OpenCvSharp 图片找茬

C# OpenCvSharp 图片找茬 目录 效果 项目 代码 下载 效果 项目 代码 using OpenCvSharp; using System; using System.Diagnostics; using System.Drawing; using System.Windows.Forms; namespace OpenCvSharp_Demo { public partial class Form1 : Form { …

初期Linux

一&#xff0c;系统分为 1.1window系统 个人 &#xff1a;win7&#xff0c;win8&#xff0c;Win10&#xff0c;Win11服务器版&#xff1a;window server 2003&#xff0c;window server 2008 1.2Linux系统 centos7redhatubantukali 1.3什么是Linux&#xff1f; Linux是基…

深入Django:用户认证与权限控制实战指南

title: 深入Django&#xff1a;用户认证与权限控制实战指南 date: 2024/5/7 18:50:33 updated: 2024/5/7 18:50:33 categories: 后端开发 tags: AuthDecoratorsPermissionsGuardianRESTAuthSessionMgmtMFA 第1章&#xff1a;入门Django与设置 1.1 Django安装与环境配置 在…

26 JavaScript学习:JSON和void

JSON 英文全称 JavaScript Object NotationJSON 是一种轻量级的数据交换格式。JSON是独立的语言JSON 易于理解。 JSON 实例 简单的 JSON 字符串实例: "{\"name\": \"Alice\", \"age\": 25, \"city\": \"San Francisco\&…

Transformer详解:从放弃到入门(三)

上篇文章中我们了解了多头注意力和位置编码&#xff0c;本文我们继续了解Transformer中剩下的其他组件。 层归一化 层归一化想要解决一个问题&#xff0c;这个问题在Batch Normalization的论文中有详细的描述&#xff0c;即深层网络中内部结点在训练过程中分布的变化问题。  …

最新版Ceph( Reef版本)块存储简单对接k8s

当前ceph 你的ceph集群上执行 1.创建名为k8s-rbd 的存储池 ceph osd pool create k8s-rbd 64 642.初始化 rbd pool init k8s-rbd3 创建k8s访问块设备的认证用户 ceph auth get-or-create client.kubernetes mon profile rbd osd profile rbd pool=k8s-rbd部署 ceph-rbd-csi …

【PCIE】基于PCIE4C的数据传输(四)——使用MSIX中断

基于PCIE4C的数据传输&#xff08;三&#xff09;——遗留中断与MSI中断 一文介绍了遗留中断与MSI中断两种中断方式的代码实现&#xff0c;本文继续基于Xilinx UltrascaleHBM VCU128开发板与linux&#xff08;RHEL8.9&#xff09;&#xff0c;介绍MSIX中断方式的代码实现。本文…

英语新概念2-回译法-lesson12

第一次翻译 &#xff08;稀巴烂&#xff09; Our neiborhood,Capitain Charles Alison,will sail from P. We will ______ in the _. He will sit in his small boat, Topsail,Topsail is a famous boat. It has been across the A many times. Alison will sail at 8 o’cloc…

每日一题(力扣740):删除并获得点数--dp+思维

其实跟打家劫舍没啥区别 排序去重之后去考虑当前位置和前两个位置之间的关系即可&#xff0c;具体见代码&#xff1a; class Solution { public:int deleteAndEarn(vector<int>& nums) {int n nums.size();if (n 1) return nums[0];unordered_map<int, int>…

LLM⊗KG范式下的知识图谱问答实现框架思想阅读

分享一张有趣的图&#xff0c;意思是在分类场景下&#xff0c;使用大模型和fasttext的效果&#xff0c;评论也很逗。 这其实背后的逻辑是&#xff0c;在类别众多的分类场景下&#xff0c;尤其是在标注数据量不缺的情况下&#xff0c;大模型的收益是否能够比有监督模型的收益更多…

multipass和multipassd命令的区别

multipassd通常是multipass服务的后台守护进程&#xff0c;它负责管理和控制虚拟机实例。 命令区别 例&#xff1a; multipass restart my-vm 这个命令用于重启Multipass中的虚拟机实例。例如有一个名为my-vm的虚拟机实例。 multipassd restart 这会重新启动Multipass后台…

Backblaze发布2024 Q1硬盘故障质量报告-1

作为一家在2021年在美国纳斯达克上市的云端备份公司&#xff0c;Backblaze一直保持着对外定期发布HDD和SSD的故障率稳定性质量报告&#xff0c;给大家提供了一份真实应用场景下的稳定性分析参考数据。 截至2024年第一季度末&#xff0c;Backblaze在其全球数据中心的云存储服务器…