QGIS3.28的二次开发八:显示shp的属性表

news2024/11/26 20:22:53

这里实现两个基本的 GIS 软件需求:矢量图层的属性表显示,以及根据属性筛选要素。

具体需求如下:

  • 加载一个矢量图层并打开其属性表;
  • 输入筛选条件确认无误后,画布上和属性表中均只显示筛选后的要素。

QGIS 提供了若干类用于实现图层属性表。属性表基于 Qt 的 QTableView 实现,利用了 QT中的Model/View 机制。QGIS 用于实现属性表所涉及到类比较多,彼此关系也不太直观, 这里仅做简单的总结。

本篇文章主要用到的与实现图层属性表相关的类有四个,分别为

QgsVectorLayerCache

该类继承自QObject,用于缓存给定QgsVectorLayer的特征,缓存的特征可以通过QgsAbstractCacheIndex进行索引,对给定用例进行适当的索引可能会大大提高性能。构造QgsAttributeTableModel时,只能使用图层的数据缓存,而不能直接使用原图层,应该是为了避免数据冲突之类的问题。

 QgsAttributeTableModel 

一个由QgsVectorLayerCache支持的模型,继承自QAbstractTableModel,它能够为QAbstractItemView提供特征/属性信息,作为QgsAttributeTableView的后端数据源。也能够为它的QModelIndexes生成编辑器小部件,在本QGIS源代码中主要被称为“主模型”。

QgsAttributeTableView

该类继承自QgsTableView,进而继承自QTableView。提供QgsVectorLayer特性的表视图,是最终显示图层属性表的视图组件。

QgsAttributeTableFilterModel

该类的继承关系如下图所示,为QSortFilterProxyModel和QgsFeatureModel的子类。其基类QSortFilterProxyModel作为数据源模型和视图的中间处理器,提供对源模型数据筛选和排序的能力。基类使用时必须通过setSourceModel()方法指定其源模型,然后调用QTreeView 的setModel()方法传入QSortFilterProxyModel这个中间模型(而非传入源模型),这样视图显示的数据就可以通过本中间模型进行排序和筛选而不影响到源模型中的数据。

运行截图

关键代码

#include "DefMainWindow.h"
#include <qgsattributetableview.h>	// 显示图层属性表的视图组件
#include <qmessagebox.h>	// 弹出提示框


DefMainWindow::DefMainWindow(QWidget *parent) :
	QMainWindow(parent),
	mCanvas(this)
{
	ui.setupUi(this);
	ui.verticalLayout->addWidget(&mCanvas);
	mpVectorLayer = new QgsVectorLayer("E:\\TestImage\\中华人民共和国\\中华人民共和国.shp", "中华人民共和国");
	// 因为图层编码为utf8,这里也需要设置编码为utf8
	mpVectorLayer->setProviderEncoding("utf-8");
	// 参数一为要缓存特征的图层,参数二为缓存的大小,这里我们直接将缓存大小设定为要素数量,即全部缓存
	mpVectorLayerCache = new QgsVectorLayerCache(mpVectorLayer, mpVectorLayer->featureCount());
	// 创建源模型
	mpAttrTableModel = new QgsAttributeTableModel(mpVectorLayerCache);
	// 在使用此模型作为任何其他中间模型的源模型之前,将该图层加载到模型中
	mpAttrTableModel->loadLayer();
	// 创建中间模型,用于制作属性表筛选器
	// 参数一为Canvas画布,参数二为源模型
	// 筛选执行的过程中,画布上同样要更新渲染(只显示筛选后的要素)
	mpAttrTableFilterModel = new QgsAttributeTableFilterModel(&mCanvas, mpAttrTableModel);
	// 为中间模型设置源模型,由于上面创建中间模型的构造函数中已经设置了源模型,所以此句可以忽略
	mpAttrTableFilterModel->setSourceModel(mpAttrTableModel);
	// 将图层加载到Canvas画布
	mCanvas.setLayers(QList<QgsMapLayer*>() << mpVectorLayer);
	// 将画布缩放到完整范围,用于显示完整图层
	mCanvas.zoomToFullExtent();
	QObject::connect(ui.btnOpenAttributeTable, &QPushButton::clicked, this, &DefMainWindow::onOpenAttributeTableButtonClicked);
	QObject::connect(ui.btnApplyWhereClause, &QPushButton::clicked, this, &DefMainWindow::onApplyWhereClauseButtonClicked);
}

// 点击“打开属性表”按钮,弹出属性表窗口
void DefMainWindow::onOpenAttributeTableButtonClicked()
{
	// 创建视图
	QgsAttributeTableView* pView = new QgsAttributeTableView(this);
	// 该方法来自QWidget,设置窗口为半模态类型
	pView->setWindowModality(Qt::WindowModality::WindowModal);
	// 设置窗口属性
	// Qt::Window 表示无论是否有父窗口部件,新窗口部件都是一个窗口,通常有一个窗口边框和一个标题栏
	pView->setWindowFlag(Qt::Window);
	// 设置窗口标题
	pView->setWindowTitle(u8"图层属性表");
	// 设置模型 void QgsAttributeTableView::setModel(QgsAttributeTableFilterModel * filterModel)	
	pView->setModel(mpAttrTableFilterModel);
	// 设置窗口大小
	pView->resize(700, 450);
	// 展示窗口
	pView->show();
}

// 输入查询语句,筛查属性值
void DefMainWindow::onApplyWhereClauseButtonClicked()
{
	// 获取输入的查询语句
	QString whereClause = ui.leWhereClause->text();
	// 设置的同时会进行查询,如果查询出现错误则返回false
	if (!mpVectorLayer->setSubsetString(whereClause))
	{
		// 如果有查询出现错误
		if (mpVectorLayer->dataProvider()->hasErrors())
		{
			// 显示记录的错误信息
			QMessageBox::warning(this, u8"错误", QString(u8"查询执行错误。返回信息:\n\n%1").arg(mpVectorLayer->dataProvider()->errors().join("\n")));
			// 清除记录的错误信息
			mpVectorLayer->dataProvider()->clearErrors();
		}
		// 如果查询字符串设置失败,而且没有错误,说明设置过滤表达式失败
		else
		{
			QMessageBox::warning(this, u8"错误", u8"设置过滤表达式失败。");
		}
	}
}

 查询功能详解

// 输入查询语句,筛查属性值
void DefMainWindow::onApplyWhereClauseButtonClicked()
{
	// 获取输入的查询语句
	QString whereClause = ui.leWhereClause->text();
	// 设置的同时会进行查询,如果查询出现错误则返回false
	if (!mpVectorLayer->setSubsetString(whereClause))
	{
		// 如果有查询出现错误
		if (mpVectorLayer->dataProvider()->hasErrors())
		{
			// 显示记录的错误信息
			QMessageBox::warning(this, u8"错误", QString(u8"查询执行错误。返回信息:\n\n%1").arg(mpVectorLayer->dataProvider()->errors().join("\n")));
			// 清除记录的错误信息
			mpVectorLayer->dataProvider()->clearErrors();
		}
		// 如果查询字符串设置失败,而且没有错误,说明设置过滤表达式失败
		else
		{
			QMessageBox::warning(this, u8"错误", u8"设置过滤表达式失败。");
		}
	}
}

(1)bool QgsVectorLayer::setSubsetString(const QString & subset)

subset可以是sql语句的where子句,也可以是特定于底层数据提供程序和数据存储的其他定义字符串。如果设置subset字符串成功则返回true,否则返回false。QgsVectorLayer::setSubsetString()方法会将用户输入的subset应用到图层上,筛选子句被设置成功后,会自动映射到以其为源的数据缓冲,即之前建立的 QgsVectorLayerCache 对象上。相应的数据源模型也将得到更改,进而中间模型也会改,最终反映到 QgsAttributeTableView 的显示上。

(2)const QgsVectorDataProvider * QgsVectorLayer::dataProvider()const 

以正确的方式返回该层的数据提供程序,它可能是nullptr。在获取和处理图层错误信息时,需要通过QgsVectorLayer::dataProvider()方法获取QgsVectorDataProvider 类。这个类是对一切矢量数据源类型的抽象,类似于数据处理的中间件。

 (3)bool QgsVectorDataProvider::hasErrors()const

查询出现错误会返回true

(4)QStringList QgsVectorDataProvider::errors()const

获取记录的错误信息

(5)void QgsVectorDataProvider::clearErrors()

清除记录的错误信息

注意:查询时输入的待查询的字符串要用单引号!

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

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

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

相关文章

V3s uboot 通过env 修改LCD 参数信息

实际项目中我们可能使用各种参数的LCD 显示器&#xff0c;有7吋&#xff0c;4.3 寸等等&#xff0c;我这里使用的uboot 版本是U-Boot 2017.01-rc2 &#xff0c;在make menuconfig 时候会填入lcd 配置信息&#xff0c;如下&#xff1a; 所以这里使用起来很不方便&#xff0c;查看…

Vulnhub: DriftingBlues: 3靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.192 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.192 查看robots.txt得到提示 访问eventadmins提示littlequeenofspades.html 查看littlequeenofspades.html源码 base64解密…

掌握Python的X篇_35_用Python为美女打码_图像库Pillow

本篇将会介绍python中的一个图像库Pillow。 文章目录 1. Pillow与PIL的关系2. 调整大小3. 加滤镜4. 剪裁5. 生成验证码 1. Pillow与PIL的关系 我们在网上搜python的图像库的话&#xff0c;可能搜到的时PIL。实际上之前python发展的时候就是PIL&#xff0c;这个库比较好用&…

IL汇编语言做一个窗体

网上看到一段代码&#xff0c; .assembly extern mscorlib {} .assembly Classes { .ver 1:0:1:0 } .namespace MyForm { .class public TestForm extends [System.Windows.Forms]System.Windows.Forms.Form { .field private class [System]…

C语言快速回顾(二)

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》&#xff0c;结合我自己的工作学习经历&#xff0c;我准备写一个音视频系列blog。C/C是音视频必…

房屋中介系统springboot框架jsp房产信息管理java源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 房屋中介系统springboot框架 系统有1权限&#xff1a…

SAP MM学习笔记19- SAP中的库存处理 单纯的退货,交货不足和过量交货

下面这篇文章讲了 SAP中的库存类型。本篇讲一些库存处理场景。 SAP MM学习笔记19- SAP中的库存类型&#xff0c;以及 保留在库的利用场景_东京老树根的博客-CSDN博客 1&#xff0c;单纯的退货 收货之后发现不合格货物&#xff0c;然后就想退货。而且退货之后不想再要了&#…

RES 系列 GRES: Generalized Referring Expression Segmentation 论文阅读笔记

RES 系列 GRES: Generalized Referring Expression Segmentation 论文阅读笔记 一、Abstract二、引言三、相关工作有关的指代任务和数据集指代分割方法 四、任务设置及数据集4.1 GRES 设置RES 回顾一般化的 RES评估 4.2 gRefCOCO&#xff1a;一个大尺度的 GRES 数据集多目标样本…

使用腾讯云轻量服务器Matomo应用模板建网站流量统计系统

腾讯云百科分享使用腾讯云轻量应用服务器Matomo应用模板搭建网站流量统计系统&#xff0c;Matomo 是一款开源的网站数据统计软件&#xff0c;可以用于跟踪、分析您的网站的流量&#xff0c;同时充分保障数据安全性、隐私性。该镜像基于 CentOS 7.6 64位操作系统&#xff0c;已预…

Docker技术入门教程

Docker技术入门教程 一、docker概念 一款产品从开发到上线&#xff0c;从操作系统&#xff0c;到运行环境&#xff0c;再到应用配置。作为开发运维之间的协作我们需要关心很多东西&#xff0c;这也是很多互联网公司都不得不面对的问题&#xff0c;特别是各种版本的迭代之后&a…

Digital thread中文术语标准化|Digital thread何时是“数字主螺纹”的意思?

文章仅供个人学习使用&#xff0c;请勿传播&#xff01; 原文来源&#xff1a; 段海波 数字孪生体实验室 2021-12-30 18:22 https://mp.weixin.qq.com/s/-bgMkSewxOsjhTiagUnfsw 作者一直以来主张区分数字孪生系统和数字孪生体&#xff0c;进而构建系统化的数字孪生概念和术语体…

时序预测 | MATLAB实现基于BiLSTM双向长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价)

时序预测 | MATLAB实现基于BiLSTM双向长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价) 目录 时序预测 | MATLAB实现基于BiLSTM双向长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价)预测结果基本介绍程序设计参考资料 预测结果 基本介绍 Matlab实现BiLST…

个人对哈希数据结构学习总结 -- 理论篇

个人对哈希数据结构学习总结 -- 理论篇 引言哈希表设计思考哈希冲突Hash Functions冲突解决开放地址法(Open Addressing)分离链表法(Separate Chaining)Two-way Chaining Dynamic Hash Tableschained Hashingextendible hashinglinear hashing说明 spiral storage 使用场景小结…

深入了解 Postman Test 校验的使用方法

Postman 是一个广泛使用的 API 开发工具&#xff0c;它允许开发人员测试 API 的各个方面&#xff0c;包括请求、响应、身份验证等等&#xff0c;其中最常用的功能之一就是 Test 校验。那今天就一起来看看 Postman 的 Test 校验该如何使用。 Test 校验是什么&#xff1f; Test…

Java中的继承

目标&#xff1a; 1&#xff0c;认识继承 Java中提供了一个关键字extends&#xff0c;用这个关键字&#xff0c;可以让一个类和另一个类建立起父子关系。 继承的特点&#xff1a; 子类可以继承父类的非私有成员&#xff08;成员变量&#xff0c;成员方法&#xff09;&#x…

LeetCode_04Java_88. 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&#xff0c;合并后数组…

第三章 图论 No.11二分图,匈牙利算法与点覆盖

文章目录 二分染色&#xff1a;257. 关押罪犯增广路径372. 棋盘覆盖 最小点覆盖376. 机器任务 最大独立集378. 骑士放置 最小路径点覆盖 二分染色&#xff1a;257. 关押罪犯 257. 关押罪犯 - AcWing题库 最大最小问题&#xff0c;一眼二分 答案的范围在 [ 1 , 1 e 9 ] [1, 1…

数据驱动与关键字驱动

初次接触自动化测试时&#xff0c;对数据驱动和关键字驱动不甚理解&#xff0c;觉得有点故弄玄须&#xff0c;不就是参数和函数其嘛&#xff01;其实其也体现了测试所不同与开发的一些特点&#xff08;主要指系统测试&#xff09;&#xff0c;以及和对技术发展的脉络的展现。 …

MyBatisPlus通用枚举

数据库表中加一个字段sex&#xff08;为int类型&#xff09; 新加一个枚举的包&#xff0c;然后创建类的时候选择枚举类 Getter public enum SexEnum {MALE(1, "男"),FEMALE(2, "女");EnumValue//将注解标识的属性的值存储到数据库中private Integer sex;…

JZ36二叉搜索树与双向链表

题目地址&#xff1a;二叉搜索树与双向链表_牛客题霸_牛客网 题目回顾&#xff1a; 解题思路&#xff1a; 由题目可知&#xff0c;这里的二叉搜索树转成双向链表的符合左根右的逻辑顺序&#xff0c;且是一个递增序列。 创建两个指针&#xff0c;一个指向head&#xff0c;一个…