QGis二次开发 —— 3、程序加载栅格tif与矢量shp文件可进行切换控制,可进行导出/导入工程(附源码)

news2024/12/26 11:51:13
效果

在这里插入图片描述

功能说明

     软件可同时加载.tif栅格图片与.shp矢量图片、加载图片后可进行自由切换查看图层、可对加载的图片进行关闭 关闭后清空图层、可对加载的图片进行导出.qgs的QGIS工程、可对.qgs的QGis工程导入并导入后可进行自由切换查看图层。

源码

     注意: 在加载tif栅格文件后会在该文件同级目录下自动创建.html文件。
     注意: .shp文件目录下应该要有对应同名的.shx矢量字体文件,这样才能加载成功。

     main.cpp

#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>

#include <qgsapplication.h>

int main(int argc, char *argv[])
{
	// 参数三: 如果需要GUI应用程序,则设置为true;对于仅控制台应用程序,设置false
 	QgsApplication a(argc, argv, true);
 	QgsApplication::setPrefixPath("D:/Software/QGis-OSGeo4W/install/apps/qgis-ltr", true);		// 设置qgis路径
	QgsApplication::setPluginPath("D:/Software/QGis-OSGeo4W/install/apps/qgis-ltr/plugins");	// 设置插件路径
 	QgsApplication::initQgis();																	// 初始化QGis

	QtWidgetsApplication1 w;
	w.show();
	return a.exec();
}


     QtWidgetsApplication1.h

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication1.h"

#include <QtMath>
#include <qgsmapcanvas.h>

class QtWidgetsApplication1 : public QMainWindow
{
    Q_OBJECT

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

protected:
	// 将画布放在ui的Widget上,供显示
	void initQgsMapCanvas();

	// 加载本地.tif、.shp文件
	bool loadLocalFile(const QString &RasterFileName, const QString &VectorFileName);

	// 删除画布上所有图层并更新画布
	void removeMapLayers();

protected slots:
	// 通过按钮驱动进行加载本地文件
	void on_btn_qgsLoadFile_clicked();
	
	// 保存QGIS工程项目
	void on_btn_SaveQgisProject_clicked();

	// 导入QGIS工程项目
	void on_btn_LoadQgisProject_clicked();

	// 关闭QGIS工程项目
	void on_btn_CloseQgisProject_clicked();

	// 切换显示画布上的矢量、栅格图层
	void sltQgsShowFile(int);

private:
    Ui::QtWidgetsApplication1Class ui;

	// 画布
	QgsMapCanvas *qMapCanvas = nullptr;

	// 图层列表: qMapLayerList为真实使用,qVirtualMapLayerList为虚拟使用。真实使用时会增删、虚拟使用则仅在函数内增加后则不再增删。
	QList<QgsMapLayer*> qMapLayerList, qVirtualMapLayerList;
};


     QtWidgetsApplication1.cpp

#include "QtWidgetsApplication1.h"

#include <QMessageBox>
#include <QComboBox>
#include <QGridLayout>

#include <qgsrasterlayer.h>
#include <qgsvectorlayer.h>
#include <qgsproject.h>

const QString QGisProjectFileName = "qgs_project.qgs";

QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent) : QMainWindow(parent)
{
    ui.setupUi(this);

	initQgsMapCanvas();
}

QtWidgetsApplication1::~QtWidgetsApplication1()
{
	removeMapLayers();

	QLayout *GridLayout = ui.qgsMapCanvasWidget->layout();
	if (GridLayout) 
	{
		GridLayout->removeWidget(qMapCanvas);
		delete GridLayout; 
	}GridLayout = nullptr;

	if (qMapCanvas) { delete qMapCanvas; }qMapCanvas = nullptr;
}

void QtWidgetsApplication1::initQgsMapCanvas()
{
	// 创建地图画布对象
	qMapCanvas = new QgsMapCanvas(this);

	QGridLayout *GridLayout = new QGridLayout;
	GridLayout->addWidget(qMapCanvas);

	ui.qgsMapCanvasWidget->setLayout(GridLayout);
}

bool QtWidgetsApplication1::loadLocalFile(const QString &RasterFileName, const QString &VectorFileName)
{
	// 创建矢量图层对象并加入本地文件
	QgsVectorLayer *qVectorLayer = new QgsVectorLayer(VectorFileName, "shp");
	if (!qVectorLayer->isValid()) { return false; }
	qMapLayerList << qVectorLayer;
	qVirtualMapLayerList << qVectorLayer;
	ui.cb_qgsShowFile->addItem("shp", 0);	// 1为qVectorLayer所在qMapLayerList的序号

 	// 创建光栅图层对象加入本地文件
	QgsRasterLayer *qRasterLayer = new QgsRasterLayer(RasterFileName, "tif");
 	if (!qRasterLayer->isValid()) { return false; }
 	// 设置对比度增强(主要用于栅格图像;矢量图像不需要)。参数1算法:线性直方图、参数2界限范围:实际最小最大值
 	qRasterLayer->setContrastEnhancement(QgsContrastEnhancement::StretchToMinimumMaximum, QgsRasterMinMaxOrigin::MinMax);
	qMapLayerList << qRasterLayer;
	qVirtualMapLayerList << qRasterLayer;
 	ui.cb_qgsShowFile->addItem("tif",1);	// 0为qRasterLayer所在qMapLayerList的序号

	// 画布设置
	qMapCanvas->setLayers(qMapLayerList);							// 设置应在画布中显示的图层列表
	qMapCanvas->setDestinationCrs(qMapLayerList[0]->crs());			// 设置目标坐标参照系为输入光栅图层的坐标系
	qMapCanvas->setExtent(qMapLayerList[0]->extent());				// 设置画布范围为输入光栅图层的范围
	qMapCanvas->setCurrentLayer(qMapLayerList[0]);					// 设置画布当前图层为输入光栅图层
	qMapCanvas->refresh();											// 刷新画布

	// 将图层列表添加到已加载图层的映射中
	QgsProject::instance()->addMapLayers(qMapLayerList);

	return true;
}

void QtWidgetsApplication1::removeMapLayers()
{
	if (!qMapLayerList.isEmpty()) 
	{
		qMapLayerList.clear(); 
		qVirtualMapLayerList.clear();
	}

	qMapCanvas->setLayers(QList<QgsMapLayer*>());
	qMapCanvas->refresh();
}

void QtWidgetsApplication1::on_btn_qgsLoadFile_clicked()
{
	loadLocalFile("./world.tif", "./china.shp");

	ui.cb_qgsShowFile->setEnabled(true);
	ui.btn_qgsLoadFile->setEnabled(false);
	connect(ui.cb_qgsShowFile, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QtWidgetsApplication1::sltQgsShowFile);
}

void QtWidgetsApplication1::on_btn_SaveQgisProject_clicked()
{
	// 工程文件扩展名为: .qgz、.qgs
	QgsProject::instance()->setFileName(QGisProjectFileName);
	QgsProject::instance()->write();
}

void QtWidgetsApplication1::on_btn_LoadQgisProject_clicked()
{
	/*****************************************************************/
	int aaa = QgsProject::instance()->count();
	int aaa1 = qMapCanvas->layerCount();

	// 加载前先将之前的画布、画布上的图层清空
	removeMapLayers();
	
	int ccc = QgsProject::instance()->count();
	int ccc2 = qMapCanvas->layerCount();
	
	/* 重要: 以上测试说明当qMapLayerList删除,那么对应画布的layer与工程实例的mapLayer也会自动清空! */
	/*****************************************************************/

	if (!QgsProject::instance()->read(QGisProjectFileName))
	{
		QMessageBox::critical(this, "ERROR", "load QGIS Project fail!", QMessageBox::Yes);
		return;
	}
	qMapLayerList = qVirtualMapLayerList = QgsProject::instance()->mapLayers().values();
	qMapCanvas->setLayers(qMapLayerList);						// 设置画布当前图层为输入光栅图层
	qMapCanvas->setDestinationCrs(qMapLayerList[0]->crs());		// 设置目标坐标参照系为输入光栅图层的坐标系
	qMapCanvas->setExtent(qMapLayerList[0]->extent());			// 设置画布范围为输入光栅图层的范围
	qMapCanvas->setCurrentLayer(qMapLayerList[0]);				// 设置画布当前图层为输入光栅图层
	qMapCanvas->refresh();										// 刷新画布

	ui.cb_qgsShowFile->addItem("shp", 0);	// 1为qVectorLayer所在qMapLayerList的序号
	ui.cb_qgsShowFile->addItem("tif", 1);	// 0为qRasterLayer所在qMapLayerList的序号
	ui.cb_qgsShowFile->setEnabled(true);
	ui.btn_qgsLoadFile->setEnabled(false);
	connect(ui.cb_qgsShowFile, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QtWidgetsApplication1::sltQgsShowFile);
	
	qDebug() << "AA:" << QgsProject::instance()->count() << "  " << QgsProject::instance()->mapLayers().count() << " " << qMapCanvas->layerCount() << "    " << qMapLayerList.size() << " " << qVirtualMapLayerList.size();
}

void QtWidgetsApplication1::on_btn_CloseQgisProject_clicked()
{
	// 加载前先将之前的画布、画布上的图层清空
	removeMapLayers();

	disconnect(ui.cb_qgsShowFile, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QtWidgetsApplication1::sltQgsShowFile);
	ui.cb_qgsShowFile->setEnabled(false);
	ui.btn_qgsLoadFile->setEnabled(true);
	ui.cb_qgsShowFile->clear();

	QgsProject::instance()->clear(); 
}

void QtWidgetsApplication1::sltQgsShowFile(int index)
{
	/* 重要: 以下操作说明qMapLayerList变化,那么对应画布的layer与工程实例的mapLayer也会自动变化! */
	if (qVirtualMapLayerList.size() > index)
	{
		qMapLayerList.clear();
		qMapLayerList << qVirtualMapLayerList[index];

		qMapCanvas->setLayers(qMapLayerList);						// 设置画布当前图层为输入光栅图层
   		qMapCanvas->setDestinationCrs(qMapLayerList[0]->crs());		// 设置目标坐标参照系为输入光栅图层的坐标系
   		qMapCanvas->setExtent(qMapLayerList[0]->extent());			// 设置画布范围为输入光栅图层的范围
   		qMapCanvas->refresh();										// 刷新画布
	}
}


     QtWidgetsApplication1.ui
在这里插入图片描述

关注

笔者 - jxd

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

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

相关文章

类和对象补充

const 成员函数 const修饰的成员函数称之为const成员函数&#xff0c;const修饰成员函数放到成员函数参数列表的后面。 void Print() const { cout << _year << "-" << _month << "-" << _day << endl; } 为什么要…

SpringDoc介绍

一、SpringDoc 官方文档 1.1何为SpringDoc SpringDoc是一个用来自动生成API文档的库。它是基于SpringBoot项目的&#xff0c;遵循OpenAPI3(一个组织规定的规范)规范。它是通过检查我们运行中的程序&#xff0c;推断出基于Spring配置、类结构和各种注解的API语义&#xff0c;从…

介绍一些免费 的 html 5模版网站 和配色 网站

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、H5 网站介绍网站 二、配色网站个人推荐 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、H5 网站介绍 以下是一些提供免费…

系统优化工具 | TweakPower v2.0.6 绿色版

TweakPower 是一款专业的系统优化工具&#xff0c;它为Windows用户提供了全面的系统性能提升解决方案。这款软件通过精细调整系统设置&#xff0c;包括注册表项&#xff0c;来显著提高电脑的运行速度和整体性能。 全面优化&#xff1a;提供内存管理、垃圾清理、数据备份、硬盘…

从 Prompt 工程看职场PUA!明明是模型缺陷,为啥要 Prompt 雕花?

简介 小伙伴们好&#xff0c;我是微信公众号《小窗幽记机器学习》的小编&#xff1a;卖豆沙饼的小女孩。在当今的人工智能领域&#xff0c;Prompt 工程已被视为一项重要技能。然而&#xff0c;这一趋势也揭示了当前模型的不足&#xff1a;一个强大的模型应当能够直接理解用户明…

20240916 每日AI必读资讯

超强o1模型智商已超120&#xff01;1小时写出NASA博士1年代码&#xff0c;最新编程赛超越99.8%选手 - 一位UCI物理学博士实测o1&#xff0c;发现自己用时1年完成的博士论文代码&#xff0c;竟被AI在1个小时之内实现了。 - o1在最新门萨智商测试中&#xff0c;IQ水平竟超过了1…

Fish Speech - 新的 TTS 解决方案

文章目录 一、关于 Fish Speech架构Fish Speech V1.1 技术介绍[视频] 二、配置1、Linux 配置2、Docker 配置 三、快速开始1、设置For Windows User / win用户For Linux User / Linux 用户 2、准备模型3、WebUI Inference 四、Break-down CLI Inference1、从语音生成 prompt:2、…

鸿蒙开发之ArkTS 基础四 函数

函数 function 是可以重复使用的代码块 提高开发效率 &#xff0c;例如下面代码: 我需要执行无变&#xff0c;最方便的就是封装到一个方法里面 然后调用五次 fn()方法即可 如图&#xff1a; 函数的步骤是先定义函数 然后使用函数 定义的语法格式是: function 函数名字(){ 函…

Linux命令:文本处理工具sed详解

目录 一、概述 二、用法 1、基本语法 2、常用选项 3、命令格式 4、编辑命令 5、获取帮助 三、 示例 1、替换字符串 2、删除行 &#xff08;1&#xff09;删除包含"string"的所有行 ​编辑 &#xff08;2&#xff09;删除从第1行到第10行的所有行 3、插…

Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 死亡对象判断方法

文章目录 垃圾回收机制死亡对象判断方法引用计数法可达性分析算法可以作为 GC Roots 的对象判断对象被回收需要经历的过程 引用类型引用汇总引用队列 废弃常量判定废弃常量废弃原因遵循原则 无用的类所需条件造成的问题解决步骤 垃圾回收机制 垃圾回收&#xff08;Garbage Col…

Anaconda安装并配置Python环境

背景概述 Anaconda&#xff0c;中文大蟒蛇&#xff0c;是一个开源的Anaconda是专注于数据分析的Python发行版本&#xff0c;包含了conda、Python等190多个科学包及其依赖项。 Anaconda就是可以便捷获取包且对包能够进行管理&#xff0c;包括了python和很多常见的软件库和一个…

[OpenCV] 数字图像处理 C++ 学习——15像素重映射(cv::remap) 附完整代码

文章目录 前言1.像素重映射理论基础2.代码实现(1) remap()细节(2)水平翻转(2)垂直翻转(3)旋转 180 度(4)径向扭曲 3.完整代码 前言 像素重映射将图像中的每个像素映射到新位置&#xff0c;实现图像的扭曲、校正等操作。在 OpenCV 中&#xff0c;cv::remap() 函数就是用于实现这…

java实现系统文件管理

java实现系统文件管理 环境&#xff1a;jdk17springbootVueElementUI 背景&#xff1a;公司所做的项目需要别的系统向我们服务器上传文件&#xff0c;当我们需要查看这些文件什么时候上传的、文件数据是怎样的&#xff0c;只能去机房&#xff0c;排查问题效率较低&#xff0c;…

Redis复习笔记整理

目录 1、Redis简介 1.1 补充数据类型Stream 1.2 Redis底层数据结构 1.3 Redis为什么快 1.4 持久化机制* 1.4.1 RDB持久化 bgsave执行流程 如何保证数据一致性 快照操作期间服务崩溃 RDB优缺点 1.4.2 AOF持久化 为什么采用写后日志 如何实现AOF 什么是AOF重写 AO…

期末满分之模拟实现字符串函数

&#xff08;一&#xff09;strcpy 首先我们来了解该函数的使用方式 最简单的理解就是“复制粘贴”&#xff0c;比如现在有一个数组arr1&#xff0c;存放着 hello &#xff1b;还有一个数组arr2&#xff0c;存放着 boy &#xff1b;那么使用该函数之后&#xff0c;形如 strcpy&…

小米,B站网络安全岗位笔试题目+答案

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 《Java代码审…

mongoDB-1

文章目录 一、疑似坑1.11.2 mongo ops manager 一、疑似坑 1.1 https://www.bilibili.com/video/BV1H1421R7WD 2.x开始用&#xff0c;现在应该6.x了吧&#xff0c;早期四处鼓吹&#xff0c;为公司打造全mongo服务&#xff0c;为并发几千做了优化&#xff0c;原本打算替代MySQ…

【C++】——list

文章目录 list介绍和使用list注意事项 list模拟实现list和vector的不同 list介绍和使用 在C中&#xff0c;list是一个带头双向链表 list注意事项 迭代器失效 删除元素&#xff1a;当使用迭代器删除一个元素时&#xff0c;指向该元素的迭代器会失效&#xff0c;但是不会影响其他…

订单防重复提交:token 发放以及校验

订单防重复提交&#xff1a;token 发放以及校验 1. 基于Token校验避免订单重复提交 1. 基于Token校验避免订单重复提交 在很多秒杀场景中&#xff0c;用户为了能下单成功&#xff0c;会频繁的点击下单按钮&#xff0c;这时候如果没有做好控制的话&#xff0c;就可能会给一个用…

ElementUI 布局——行与列的灵活运用

ElementUI 布局——行与列的灵活运用 一 . 使用 Layout 组件1.1 注册路由1.2 使用 Layout 组件 二 . 行属性2.1 栅格的间隔2.2 自定义元素标签 三 . 列属性3.1 列的偏移3.2 列的移动 在现代网页设计中&#xff0c;布局是构建用户界面的基石。Element UI 框架通过其强大的 <e…