QGIS二次开发四:实现图层列表

news2024/12/24 9:17:28

在实际开发中我们通常会遇到同时显示多个图层,并且还要实时显示和隐藏各图层的需求,如同 ArcGIS 的图层列表那样,界面左侧显示图层列表,列出当前已加载的所有图层,同时每个图层前面有复选框可以控制图层的显示/隐藏;界面右侧为画布,按图层列表的适当顺序显示所有未隐藏的图层。具体该怎么实现呢?

代码 

#include <qgsapplication.h>	// 管理图形界面
#include <qgsproviderregistry.h>	// 设置并检查数据插件目录
#include <qgsmapcanvas.h>	// 创建画布
#include <qgsvectorlayer.h>	// 用于创建矢量图层
#include <qgslayertree.h>	// 提供命名空间,包含用于层树操作的辅助函数
#include <qgslayertreemodel.h>	// 创建模型
#include <qgslayertreeview.h>	// 创建view
#include <qboxlayout.h>		// 创建布局
#include <qgsproject.h>	// 管理qgis工程的头文件

// 自定义控件LayerTreeDemo,继承自QWidget
class LayerTreeDemo :
	public QWidget
{
public:

	LayerTreeDemo(QWidget * parent = 0);

private:
	// 画布
	QgsMapCanvas mMapCanvas;
	// 图层树 View
	// QgsLayerTreeView 是 QTreeView 的子类,进而是QWidget的子类
	QgsLayerTreeView mLayerTreeView;
	// 更新画布图层的“事件回调”
	void updateCanvasLayerSet();
};

// 构造函数
LayerTreeDemo::LayerTreeDemo(QWidget * parent) :
	QWidget(parent),
	mMapCanvas(this),
	mLayerTreeView(this) {
	// layerTreeRoot() 返回指向项目层树的根(不可见)节点的指针
	QgsLayerTree* pLayerTreeRoot = QgsProject::instance()->layerTreeRoot();
	// visibilityChanged当树中节点的检查状态被更改时触发
	QObject::connect(pLayerTreeRoot, &QgsLayerTreeNode::visibilityChanged, this, &LayerTreeDemo::updateCanvasLayerSet);
	// 模型监听层树中的更改,并适当地发出更改信号,以便使用该模型的任何视图都相应地更新,参数填根节点
	QgsLayerTreeModel* pLayerTreeModel = new QgsLayerTreeModel(pLayerTreeRoot);
	// 设置模型标志	QgsLayerTreeModel::Flag,Flag为枚举类型
	// AllowNodeChangeVisibility允许用户使用复选框设置节点可见性
	pLayerTreeModel->setFlag(QgsLayerTreeModel::AllowNodeChangeVisibility);
	// model只接收QgsLayerTreeModel,视图进行模型的绑定
	mLayerTreeView.setModel(pLayerTreeModel);
	// 设置一下最大宽度以便给画布留出更多显示空间,是QWidget的函数
	mLayerTreeView.setMaximumWidth(200);  
	// 创建一个水平布局
	QHBoxLayout* pLayout = new QHBoxLayout();
	// addWidget()传入一个指针
	// mLayerTreeView控件放在左边
	pLayout->addWidget(&mLayerTreeView);
	// mMapCanvas控件放在右边
	pLayout->addWidget(&mMapCanvas);
	// 设置布局到此窗体,setLayout是QWidget的函数
	this->setLayout(pLayout);
	this->resize(1000, 600);  // 设置窗体尺寸为 1000 * 600
	this->setWindowTitle(u8"QGIS 二次开发:图层树");  // 设置窗体标题
	// 从磁盘 .shp 文件创建矢量图层
	QgsVectorLayer* pVectorLayer_1 = new QgsVectorLayer("E:\\TestImage\\深圳各区矢量图\\宝安区\\宝安区_中华人民共和国.shp", "中华人民共和国");
	QgsVectorLayer* pVectorLayer_2 = new QgsVectorLayer("E:\\TestImage\\深圳各区矢量图\\宝安区\\宝安区_省界.shp", "省界");
	QgsVectorLayer* pVectorLayer_3 = new QgsVectorLayer("E:\\TestImage\\深圳各区矢量图\\宝安区\\宝安区_市界.shp", "市界");
	QgsVectorLayer* pVectorLayer_4 = new QgsVectorLayer("E:\\TestImage\\深圳各区矢量图\\宝安区\\宝安区_县界.shp", "县界");
	QgsVectorLayer* pVectorLayer_5 = new QgsVectorLayer("E:\\TestImage\\深圳各区矢量图\\宝安区\\宝安区_乡镇边界.shp", "乡镇边界");
	// 确认图层是否创建成功
	qDebug() << "Is layer valid:" << pVectorLayer_1->isValid();
	qDebug() << "Is layer valid:" << pVectorLayer_2->isValid();
	qDebug() << "Is layer valid:" << pVectorLayer_3->isValid();
	qDebug() << "Is layer valid:" << pVectorLayer_4->isValid();
	qDebug() << "Is layer valid:" << pVectorLayer_5->isValid();
	// 把图层添加到工程,越先添加的图层,越靠近底部
	QgsProject::instance()->addMapLayer(pVectorLayer_1);
	QgsProject::instance()->addMapLayer(pVectorLayer_2);
	QgsProject::instance()->addMapLayer(pVectorLayer_3);
	QgsProject::instance()->addMapLayer(pVectorLayer_4);
	QgsProject::instance()->addMapLayer(pVectorLayer_5);
	// 执行回调函数,将图层添加到画布
	updateCanvasLayerSet();
	// 缩放到全图
	mMapCanvas.zoomToFullExtent();
}

void LayerTreeDemo::updateCanvasLayerSet()
{
	// 设置应该在画布上显示的层列表
	// layerTreeRoot()返回一个QgsLayerTreeNode
	// checkedLayers()返回属于此节点或其子节点的所有已选中层的列表
	mMapCanvas.setLayers(QgsProject::instance()->layerTreeRoot()->checkedLayers());
	// 重新绘制画布地图
	mMapCanvas.refresh();
}

int main(int argc, char **argv)
{
	// 创建 QgsApplication 实例
	QgsApplication app(argc, argv, true);

	// 设置并检查数据插件目录
	QgsProviderRegistry::instance("D:\\OSGeo4W\\apps\\qgis-ltr\\plugins");

	// 控制台打印已载入的插件目录
	qDebug() << "QGIS data providers loaded:" << QgsProviderRegistry::instance()->providerList();

	// 设置 GDAL 数据目录环境变量
	qputenv("GDAL_DATA", "D:\\OSGeo4W\\apps\\gdal\\share\\gdal");

	// 创建主窗体
	LayerTreeDemo w;
	w.show();

	// 启动 QgsApplication 实例
	return app.exec();
}

讲解

一、QgsLayerTreeView

头文件<qgslayertreeview.h>

继承自QTreeView,进而继承自QWidget

QGIS API Documentation: QgsLayerTreeView Class Reference

二、QgsProject

需要头文件<qgsproject.h>

QGIS API Documentation: QgsProject Class Reference

封装一个QGIS项目,包括一组地图层及其样式、布局、注释、画布等。

QgsProject既可以作为单个对象(QgsProject::instance())使用,也可以作为独立对象使用。QGIS项目单例总是允许访问主QGIS应用程序中打开的规范项目引用。

layerTreeRoot() 返回指向项目层树的根(不可见)节点的指针。

 三、QgsLayerTree

头文件<qgslayertree.h>

QGIS API Documentation: QgsLayerTree Class Reference

 四、QgsLayerTreeModel

头文件<qgslayertreemodel.h>

QGIS API Documentation: QgsLayerTreeModel Class Reference 

QgsLayerTreeModel类是Qt项目视图框架的模型实现。该模型可以在任何QTreeView中使用,但是建议与QgsLayerTreeView一起使用,它为层树处理带来了额外的功能。模型监听层树中的更改,并适当地发出更改信号,以便使用该模型的任何视图都相应地更新。模型的行为可以用标志来定制。例如,是否显示图例或是否允许更改层树。

 

 五、void QgsLayerTreeView::setModel(QAbstractItemModel * model)

QGIS API Documentation: QgsLayerTreeView Class Reference

model只接收QgsLayerTreeModel

六、addMapLayer()

 QGIS API Documentation: QgsProject Class Reference

把图层添加到工程和把图层添加到画布两者并没有必然关系。加入工程的图层并不一定在画布上显示(如隐藏的图层),加入画布的图层也并不一定属于工程(如额外创建一个 QgsMapCanvas 显示与当前工程无关的图层,一个例子是 QGIS 软件选择坐标系的时候,界面上会有一个小画布显示当前所选坐标系在地球上的适用范围)。

 七、setLayers()

QGIS API Documentation: QgsMapCanvas Class Reference

 设置应该在画布上显示的层列表 

八、checkedLayers()

QGIS API Documentation: QgsLayerTreeNode Class Reference

 属于QgsLayerTreeNode的函数,返回属于此节点或其子节点的所有已选中层的列表。

九、refresh() 

 QGIS API Documentation: QgsMapCanvas Class Reference

对画布的地图进行重新绘画 。

运行效果

参考文章 文章页 | mriiiron's blog 

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

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

相关文章

虾皮运营每天需要做什么?如何处理后台数据?

#shopee#​有很多朋友想做电商&#xff0c;但是对电商运营比较朦胧&#xff0c;不知道电商运营每天到底该做些什么。今天咱们就来解析下&#xff0c;Shopee电商运营每天该做哪些事情一个合格的电商运营&#xff0c;每天都会做好以下几点&#xff1a; 一、查看数据&#xff1a; …

echarts自动轮播tooltip

1. 将自动轮播的工具函数封装到 utils/echart-tooltip-carousel.js /*** echarts自动轮播tooltip* param {Object} chart echart实例* param {Number} num 轮播数量* param {Number} time 轮播间隔时间*/ export function loopShowTooltip(chart, num20, time2000) {let count…

如何配置一个永久固定的公网TCP地址来SSH远程树莓派?

文章目录 如何配置一个永久固定的公网TCP地址来SSH远程树莓派&#xff1f;前置条件命令行使用举例&#xff1a;修改cpolar配置文件 1. Linux(centos8)安装redis数据库2. 配置redis数据库3. 内网穿透3.1 安装cpolar内网穿透3.2 创建隧道映射本地端口 4. 配置固定TCP端口地址4.1 …

IoT 物联网安全事件的持续检测和监控解决方案

对于IoT物联网安全事件的持续检测和监控&#xff0c;可以采用以下解决方案&#xff1a; 设备管理和漏洞修复&#xff1a;确保设备的固件和软件及时更新&#xff0c;并修补已知的漏洞。建立一个设备清单&#xff0c;并定期审查和更新其中的设备。 流量分析和异常检测&#xff1a…

蓝牙资讯|苹果发布AirPods最新开发者固件,最新功能引人关注

苹果面向 AirPods 耳机发布了开发者固件更新 AirPods 6.0 Beta 3&#xff0c;最新内部版本号为 6A5289c。 本次更新适用于 AirPods 3、AirPods Pro 2 和 AirPods Max&#xff0c;不过并非所有 AirPods 耳机都获得了更新。包含5 种新功能 / 新特性&#xff1a; 自适应音频&am…

virtualBox桥接模式下openEuler镜像修改IP地址、openEule修改IP地址、openEule设置IP地址

安装好openEuler后,设置远程登入前,必不可少的一步,主机与虚拟机之间的通信要解决,下面给出详细步骤: 第一步:检查虚拟机适配器模式:桥接模式 第二步:登入虚拟机修改IP cd /etc/sysconfig/network-scripts vim ifcfg-enpgs3 没有vim的安装或者用vi代替:sudo dnf …

【实操干货】如何开始用Qt Widgets编程?(二)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 在本文中&#xff0…

代理模式——静态代理与动态代理

代理模式 代理模式允许你为其他对象提供一个代理&#xff0c;以控制对这个对象的访问。代理模式在不改变实际对象的情况下&#xff0c;可以在访问对象时添加额外的功能。 可以理解为代理模式为被代理对象创造了一个替身&#xff0c;调用者可以通过这个替身去实现这个被代理对…

【高危】Microsoft Office Visio 远程执行代码漏洞

漏洞描述 Microsoft Office Visio 是微软公司开发的一款流程图和矢量图绘制工具。 Microsoft Office Visio 受影响版本中&#xff0c;当解析攻击者恶意制作的Visio文件时&#xff0c;攻击者可以在应用程序上下文执行任意代码。 漏洞名称Microsoft Office Visio 远程执行代码…

大厂容器云实践之路(四)

7-爱奇艺基于 Docker 的 App Engine 实践 背景 业务上 虚机承载的业务&#xff1a; 后台服务&#xff1a;25% worker&#xff1a;20% 其他&#xff1a;55% 技术上 2014年第三季度 出发点 目标 道路曲折 用户受益 • 资源到位快 • 部署快&#xff08;上线、升级&…

神码ai伪原创文章生成器软件【php源码】

大家好&#xff0c;本文将围绕python二级用哪个版本的软件展开说明&#xff0c;二级python 值不值得考是一个很多人都想弄明白的事情&#xff0c;想搞清楚python二级用什么软件需要先了解以下几个事情。 火车头采集ai伪原创插件截图&#xff1a; 问题一&#xff1a;安装python…

小红书攻略:爆款引流,如何在激烈竞争中脱颖而出?

小红书&#xff08;RED&#xff09;作为国内最具影响力的社交电商平台之一&#xff0c;是很多品牌运营者的首选之一。然而&#xff0c;在小红书的激烈竞争中&#xff0c;如何快速引流、吸引关注&#xff0c;成为了品牌运营者面临的挑战。本篇文章一秒推小编将为您介绍小红书运营…

【SpringCloud】深入探究Eureka:构建微服务架构中的高效服务发现系统

&#x1f468;‍&#x1f4bb;博主主页&#xff1a;小尘要自信 在现代的软件开发中&#xff0c;微服务架构已经成为了一个热门的话题。微服务架构的一个关键组成部分就是服务发现。而在服务发现领域&#xff0c;Eureka无疑是一个备受推崇的解决方案。本篇博客将为您介绍什么是E…

MATLAB|信号处理的Simulink搭建与研究

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

[保研/考研机试] KY235 进制转换2 清华大学复试上机题 C++实现

题目链接&#xff1a; KY235 进制转换2 https://www.nowcoder.com/questionTerminal/ae4b3c4a968745618d65b866002bbd32 描述 将M进制的数X转换为N进制的数输出。 输入描述&#xff1a; 输入的第一行包括两个整数&#xff1a;M和N(2<M,N<36)。 下面的一行输入一个数…

【分布式技术专题】「数据一致性体系」带你一同建立采用消息队列实现的数据一致性框架技术体系方案

带你一同建立采用消息队列实现的数据一致性框架技术体系方案 分布式服务数据一致性问题采用分布式事务3PC模式3PC模式阶段分析 采用分布式锁采用数据同步机制采用数据分片机制针对常规方案所具有的问题预发送消息阶段切换为可发送状态定时补偿更新为可发送状态定时补偿发送数据…

免费ai写作生成器帮你释放创作天赋

喂&#xff01;听说你想提升写作功力&#xff1f;那么恭喜你&#xff0c;现在流行的ai写作软件将成为你提升写作效率的秘密武器。这是一款革命性的应用&#xff0c;就像你的个人写作导师&#xff0c;会帮助你通过简单的几步&#xff0c;创造出令人瞠目结舌的文字作品&#xff0…

QPainter - 使用一个时钟项目从头开始看QPainter

文章目录 QPainter - 使用一个时钟项目从头开始看QPainter绘制的原理绘制时分秒指针绘制背景绘制刻度线完整代码 QPainter - 使用一个时钟项目从头开始看QPainter 之前一直在说绘制&#xff0c;但是没有从头详细的去了解绘制这块的写法&#xff0c;因此我们来使用一个时钟的项…

3.正则表达式

3.1什么是正则表达式 ●正则表达式( Regular Expression) 是用于匹配字符串中字符组合的模式。在JavaScript中&#xff0c; 正则表达式也是对象 ●通常用来查找、替换那些符合正则表达式的文本&#xff0c;许多语言都支持正则表达式 ●正则表达式在JavaScript中的使用场景: ➢…

平板触控笔买哪种好?便宜又好用的电容笔推荐

或许很多人会觉得&#xff0c;苹果原装的电容笔性能强悍&#xff0c;是无可替代的&#xff0c;但我觉得&#xff0c;还是要看我们的预算。苹果Pencil对绘画要求不高的用户来说&#xff0c;价格太高了&#xff0c;如果我们只是用来写东西的话&#xff0c;我们甚至可以选择平替电…