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

在实际开发中我们通常会遇到同时显示多个图层,并且还要实时显示和隐藏各图层的需求,如同 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 * 600this->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.rhkb.cn/news/82958.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

边写代码边学习之numpy

1. numpy.matmul() 用法 matmul() 用于计算两个数组的矩阵乘积。示例如下 def matmul_test():array1 np.array([[[1.0, 3], [1, 1], [2, 3]]])array2 np.array([[2, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0],[1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0], ])result np.matmul(array1, …

浅谈什么是 Spring Cloud,快速学习与使用案例(文末送书福利3.0)

文章目录 &#x1f4cb;前言&#x1f3af;什么是 Spring Cloud&#x1f3af;快速入门 Spring Cloud&#x1f9e9;使用 Eureka 进行服务注册和发现 &#x1f4dd;最后&#x1f3af;文末送书&#x1f4da;内容介绍&#x1f4da;作者介绍 &#x1f525;参与方式 &#x1f4cb;前言…

nginx负载均衡(nginx结束)

本节主要内容 1、四层&#xff0c;七层代理的配置方法 2、负载均衡的算法 nginx负载均衡&#xff1a;反向代理来实现 反向代理有两种转发方式&#xff1a;1、四层代理 2、七层代理 Nginx的七层代理和四层代理 七层是最常见的反向代理方式&#xff0c;只能配置在nginx配置文…

[保研/考研机试] KY129 简单计算器 浙江大学复试上机题 C++实现

描述 读入一个只包含 , -, *, / 的非负整数计算表达式&#xff0c;计算该表达式的值。 输入描述&#xff1a; 测试输入包含若干测试用例&#xff0c;每个测试用例占一行&#xff0c;每行不超过200个字符&#xff0c;整数和运算符之间用一个空格分隔。没有非法表达式。当一行中…

设计模式——单例模式(懒汉和饿汉)

单例模式 一、概念 单例模式是一种对象创建型模式&#xff0c;使用单例模式&#xff0c;可以保证为一个类只生成唯一的实例对象。也就是说&#xff0c;在整个程序空间中&#xff0c;该类只存在一个实例对象。一个类只能有一个实例在生活中是很常见的&#xff0c;比如打印机程…

Clickhouse 数据存储

一、数据分区 数据是以分区目录的形式组织的&#xff0c;每个分区独立分开存储.这种形式&#xff0c;查询数据时&#xff0c;可以有效的跳过无用的数据文件。 1.1 数据分区的规则 分区键的取值&#xff0c;生成分区ID&#xff0c;分区根据ID决定。根据分区键的数据类型不同&am…

【论文阅读】基于深度学习的时序异常检测——TimesNet

系列文章链接 参考数据集讲解&#xff1a;数据基础&#xff1a;多维时序数据集简介 论文一&#xff1a;2022 Anomaly Transformer&#xff1a;异常分数预测 论文二&#xff1a;2022 TransAD&#xff1a;异常分数预测 论文三&#xff1a;2023 TimesNet&#xff1a;基于卷积的多任…

Webpack5新手入门简单配置

1.初始化项目 yarn init -y 2.安装依赖 yarn add -D webpack5.75.0 webpack-cli5.0.0 3.新建index.js 说明&#xff1a;写入下面的一句话 console.log("hello webpack"); 4.执行命令 说明&#xff1a;如果没有安装webpack脚手架就不能执行yarn webpack&#xff08…

【cs61b】学习笔记day2

历史文章目录 【cs61b】学习笔记day1 文章目录 历史文章目录List两个小问题bits声明一个变量引用类型方框和指针表示法数组的实例化链表 SLList List 两个小问题 思考下面两个代码分别输出什么 Walrus a new Walrus(1000, 8.3); Walrus b; b a; b.weight 5; System.out.…

ubuntu搭建wifi热点,共享网络(x86、arm相同)

目录 1 首先检查网络管理器服务是否开启 &#xff08;ubuntu需要界面&#xff09; 2 创建并配置需要共享的wifi 首先&#xff0c;明确下这篇文章说的是啥&#xff0c;是为了在ubuntu系统的电脑上&#xff0c;搭建一个wifi热点&#xff0c;供其他移动设备连接上网。就像你…

Smart HTML Elements 16.1 Crack

Smart HTML Elements 是一个现代 Vanilla JS 和 ES6 库以及下一代前端框架。企业级 Web 组件包括辅助功能&#xff08;WAI-ARIA、第 508 节/WCAG 合规性&#xff09;、本地化、从右到左键盘导航和主题。与 Angular、ReactJS、Vue.js、Bootstrap、Meteor 和任何其他框架集成。 智…

Linux常用命令大全

目录操作 切换目录 cd 查看目录 ls -l 列出文件详细信息 或者直接ll-a 列出当前目录下所有文件及目录&#xff0c;包括隐藏的a(all) 创建目录 mkdir -p 创建目录&#xff0c;若无父目录&#xff0c;则创建p(parent) 输出信息 echo 打印文件到命令行(查看文件) cat 改变…

stm32与上位机电脑间最快的通信方式是什么?

对于小型多关节机械臂的控制电路设计&#xff0c;选择合适的通信方式可以提高MCU与上位机之间的实时性。以下是一些在STM32上常用的通信方式&#xff0c;你可以根据你的具体需求选择适合的&#xff1a; 串口通信&#xff08;UART&#xff09;&#xff1a;串口通信是一种常见的…

【stm32】初识stm32—stm32环境的搭建

文章目录 &#x1f6f8;stm32资料分享&#x1f354;stm32是什么&#x1f384;具体过程&#x1f3f3;️‍&#x1f308;安装驱动&#x1f388;1&#x1f388;2 &#x1f3f3;️‍&#x1f308;建立Start文件夹 &#x1f6f8;stm32资料分享 我用夸克网盘分享了「STM32入门教程资料…

【单片机】51单片机串口的收发实验,串口程序

这段代码是使用C语言编写的用于8051单片机的串口通信程序。它实现了以下功能&#xff1a; 引入必要的头文件&#xff0c;包括reg52.h、intrins.h、string.h、stdio.h和stdlib.h。 定义了常量FSOC和BAUD&#xff0c;分别表示系统时钟频率和波特率。 定义了一个发送数据的函数…

关于eclipse导入部署具有增删改查的项目

目录 前言&#xff1a;当我们刚刚进入公司的第一步就是去部署当前公司的项目&#xff0c;本博客就是详细介绍怎么去部署当前公司的项目。 一&#xff0c;开发工具&#xff1a; 二&#xff0c;具体步骤&#xff1a; 2.1导入公司的项目 打开eclipse开发工具 2.2配置当前的环…

下载网络文件到本地

文章目录 目录 前言 操作步骤 1.引入 2.读取出文件内容 3.筛选出URL 4.下载表情包 总结 前言 这里记录一次用代码下载网络文件的过程&#xff0c;以获取抖音表情包为例。 一、操作步骤 1.引入 首先抖音有网页版&#xff0c;用浏览器就可以观看&#xff0c;用户评论发布表情在…

蓝桥杯上岸每日N题 第八期 (全球变暖)!!!

蓝桥杯上岸每日N题第八期(全球变暖)&#xff01;&#xff01;&#xff01; 同步收录 &#x1f447; 蓝桥杯上岸必背&#xff01;&#xff01;&#xff01;(第五期BFS) 大家好 我是寸铁&#x1f4aa; 冲刺蓝桥杯省一模板大全来啦 &#x1f525; 蓝桥杯4月8号就要开始了 &am…

MAPPO 算法的深度解析与应用和实现

【论文研读】 The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games 说明&#xff1a; 来源&#xff1a;36th Conference on Neural Information Processing Systems (NeurIPS 2022) Track on Datasets and Benchmarks. 是NIPS文章&#xff0c;质量有保障&…

黑马机器学习day2

1.1sklearn转换器和估计器 转换器和预估器&#xff08;estimator&#xff09; 1.1.1转换器 实例化一个转换器类 Transformer调用fit_transform() 转换器调用有以下几种形式&#xff1a; fit_transformfittransform 1.1.2估计器 在sklearn中&#xff0c;估计器是一…