QGis(三)查询矢量图层的要素属性字段值(转载)
QGis(三)查询矢量图层的要素属性字段值
https://github.com/gwaldron/osgearth/issues/489
当加载一个矢量图层后,如果要查看要素的属性字段值,则需要实现identity的功能。可以和前面的缩放一样,添加一个工具栏按钮:
(1)在MainWindow添加一个变量,并在Qt设计师里添加Action:
QgsMapToolSelect *mpIdentifyTool; ///<查询要素
这里QgsMapToolSelect类继承自QgsMapTool,后面再列出详细内容。
(2)然后在初始化函数里添加:
mpMapToolBar->addAction(ui.mpActionIdentify); mpIdentifyTool = new QgsMapToolSelect(mainMapCanvas); mpIdentifyTool->setAction(ui.mpActionIdentify);
(3)添加信号槽函数连接:
connect(ui.mpActionIdentify, SIGNAL(triggered()), this, SLOT(identifyFeature()));
(4)槽函数实现:
void MainWindow::identifyFeature()
{
mpIdentifyTool->SetEnable(true);
mainMapCanvas->setMapTool(mpIdentifyTool);
ui.mpActionIdentify->setCheckable(true);
ui.mpActionIdentify->setChecked(true);
)->type() == QgsMapLayer::RasterLayer)
{
return;
}
QgsVectorLayer *pLayer=(QgsVectorLayer *)mainMapCanvas->layer();
mpIdentifyTool->SetSelectLayer(pLayer);
if ( ui.mpActionIdentify->isChecked())
{
pLayer->removeSelection(true);
}
}
可以看到,基本步骤就跟前面的缩放工具栏一模一样。但是QgsMapToolSelect不是 QgsMapTool自带的类,需要自定义,QgsMapToolSelect类的定义如下:
class QgsMapToolSelect :
public QgsMapTool
{
Q_OBJECT;
public:
QgsMapToolSelect(QgsMapCanvas *);
~QgsMapToolSelect(void);
public:
//设置当前被选择(活动)的图层
void SetSelectLayer(QgsVectorLayer *);
<span style="white-space:pre"> </span>//重载鼠标释放事件函数
virtual void canvasReleaseEvent(QMouseEvent * e);
//设定工具状态
void SetEnable(bool);
//得到所有的属性和属性值,<属性1,属性值1>是QMap的一对值
QList<QMap<QString, QString>> GetAttributeValue(QgsVectorLayer *layer, QgsFeatureIds selectedFIds);
void setShowFlag(bool flag);
IdentifyResultDlg *ResultDlg();
private:
QgsVectorLayer* pLayer;
QgsFeatureIds layerSelectedFeatures;
bool StatusFlag;
QList<QMap<QString, QString>> list; //存储选择后的要素
bool isShowFlag; ///< 是否在主界面上勾选了shp图层
IdentifyResultDlg *mIdentifyResultDlg;
private:
<span style="white-space:pre"> </span>//提取鼠标位置一定范围作为选择区域
void ExpandSelectRangle(QRect &Rect,QPoint Point);
//将指定的设备坐标区域转换成地图坐标区域
void SetRubberBand(QRect &selectRect,QgsRubberBand *);
//选择图层特征
void SetSelectFeatures(QgsGeometry *,bool,bool,bool);
void SetSelectFeatures(QgsGeometry *,bool);
};
具体函数实现:
#include "qgsmaptoolselect.h"
//构造和析构函数
QgsMapToolSelect::QgsMapToolSelect(QgsMapCanvas *Mapcanvas):QgsMapTool(Mapcanvas)
{
pLayer=NULL;
mCursor=Qt::ArrowCursor;
mCanvas=Mapcanvas;
StatusFlag=true;
isShowFlag = true;
mIdentifyResultDlg = NULL;
}
QgsMapToolSelect::~QgsMapToolSelect(void)
{
}
//设置当前被选择(活动)的图层
void QgsMapToolSelect::SetSelectLayer(QgsVectorLayer *Layer)
{
pLayer=Layer;
}
//鼠标按钮释放时,选择包含鼠标位置的图元
void QgsMapToolSelect::canvasReleaseEvent(QMouseEvent * e )
{
if(mCanvas==NULL){
return;
}
if(pLayer==NULL){
QMessageBox::about(mCanvas,QString::fromLocal8Bit("警告"),QString::fromLocal8Bit("请选择图层"));
return;
}
if(StatusFlag==false){
return;
}
//得到产生事件的按钮信息
Qt::MouseButton mButton=e->button();
//如果不是左按钮返回
if(mButton!=Qt::MouseButton::LeftButton){
return;
}
//得到鼠标指针的位置
QPoint pos=e->pos();
//定义QgsRubberBand对象
QgsRubberBand rubberBand(mCanvas,true);
QRect selectRect(,,,);
//设置鼠标位置区域
ExpandSelectRangle(selectRect,pos);
//将鼠标位置区域转换成地图坐标
SetRubberBand(selectRect,&rubberBand );
//将QgsRubberBand对象转换为几何对象,根据该几何对象在图层中选择特征
QgsGeometry* selectGeom=rubberBand.asGeometry();
if(!selectGeom){
return;
}
//确定是否按下ctrl键
bool doDifference=e->modifiers()&Qt::ControlModifier ? true:false;
//在图层中选择最靠近几何对象的特征
SetSelectFeatures(selectGeom,false,doDifference,true);
//SetSelectFeatures(selectGeom,doDifference);
//设定选择的特征
pLayer->setSelectedFeatures(layerSelectedFeatures);
list = GetAttributeValue(pLayer, layerSelectedFeatures);
if (isShowFlag)
{
ResultDlg()->InitialData(list);
ResultDlg()->show();
}
else
{
QMessageBox::information(NULL, tr("警告"), tr("请选择矢量图层"), QMessageBox::Ok);
}
delete selectGeom;
rubberBand.reset(true);
}
//提取鼠标位置一定范围作为选择区域
void QgsMapToolSelect::ExpandSelectRangle(QRect &Rect,QPoint Point)
{
;
//如果图层不是面图元类型
if(pLayer->geometryType()!=QGis::Polygon){
boxSize=;
}
else{
boxSize=;
}
//设置选择区域
Rect.setLeft(Point.x()-boxSize);
Rect.setRight(Point.x()+boxSize);
Rect.setTop(Point.y()-boxSize);
Rect.setBottom(Point.y()+boxSize);
}
//将指定的设备坐标区域转换成地图坐标区域
void QgsMapToolSelect::SetRubberBand(QRect &selectRect,QgsRubberBand *pRubber)
{
//得到当前坐标变换对象
const QgsMapToPixel* transform=mCanvas->getCoordinateTransform();
//将区域设备坐标转换成地图坐标
QgsPoint ll=transform->toMapCoordinates(selectRect.left(),selectRect.bottom());
QgsPoint ur = transform->toMapCoordinates(selectRect.right(),selectRect.top());
pRubber->reset(true );
//将区域的4个角点添加到QgsRubberBand对象中
pRubber->addPoint(ll,false );
pRubber->addPoint(QgsPoint(ur.x(), ll.y()),false );
pRubber->addPoint(ur,false );
pRubber->addPoint(QgsPoint( ll.x(), ur.y() ),true );
}
//选择几何特征
//selectGeometry:选择特征的选择几何体
//doContains:选择的特征是否包含在选择几何体内部
//singleSelect:仅仅选择和选择几何体最靠近的特征
void QgsMapToolSelect::SetSelectFeatures(QgsGeometry *selectGeometry,bool doContains,
bool doDifference,bool singleSelect)
{
//如果选择几何体不是多边形
if(selectGeometry->type()!=QGis::Polygon){
return;
}
QgsGeometry selectGeomTrans(*selectGeometry);
//设定选择几何体的坐标系和图层的坐标系一致
if(mCanvas->mapRenderer()->hasCrsTransformEnabled()){
try{
//将地图绘板坐标系变换到图层坐标系
QgsCoordinateTransform ct(mCanvas->mapRenderer()->destinationSrs(),pLayer->crs());
//设定几何体的坐标系和图层坐标系一致
selectGeomTrans.transform(ct);
}
//对于异常点抛出异常
catch(QgsCsException &cse){
Q_UNUSED(cse);
//catch exception for 'invalid' point and leave existing selection unchanged
QMessageBox::warning(mCanvas, QObject::tr("CRS Exception"),
QObject::tr( "Selection extends beyond layer's coordinate system." ) );
return;
}
}
//设置光标
//QApplication::setOverrideCursor(Qt::WaitCursor);
//选择和选择几何体相交或在几何体内部的特征
pLayer->select(QgsAttributeList(),selectGeomTrans.boundingBox(),true,true);
int nh=pLayer->selectedFeatureCount();
QgsFeatureIds newSelectedFeatures;
QgsFeature f;
;
bool foundSingleFeature=false;
double closestFeatureDist=std::numeric_limits<double>::max();
//得到当前选择的特征
while(pLayer->nextFeature(f)){
QgsGeometry* g=f.geometry();
//g是否包含在selectGeomTrans几何体内部
if(doContains && !selectGeomTrans.contains(g)){
continue;
}
if(singleSelect){ //选择和几何体最靠近的特征
foundSingleFeature=true;
//计算两个几何体之间的距离
double distance=g->distance(selectGeomTrans);
if(distance<=closestFeatureDist){
closestFeatureDist=distance;
//计算出最靠近选择几何体特征的id
closestFeatureId=f.id();
}
}
else{ //存储符合要求的特征id
newSelectedFeatures.insert(f.id());
}
}
//确定和选择几何体最靠近特征的id
if(singleSelect && foundSingleFeature){
newSelectedFeatures.insert(closestFeatureId);
}
//如果按下ctrl键,选择多个特征
if(doDifference){
//得到所有选择特征的id
layerSelectedFeatures=pLayer->selectedFeaturesIds();
QgsFeatureIds::const_iterator i=newSelectedFeatures.constEnd();
while(i!=newSelectedFeatures.constBegin()){
--i;
if(layerSelectedFeatures.contains(*i)){
layerSelectedFeatures.remove( *i );
}
else{
layerSelectedFeatures.insert( *i );
}
}
}
else{
layerSelectedFeatures=newSelectedFeatures;
}
//QApplication::restoreOverrideCursor();
}
//选择几何特征,用于选择面状几何特征
//selectGeometry:选择几何体
void QgsMapToolSelect::SetSelectFeatures(QgsGeometry *selectGeometry,bool doDifference)
{
//如果选择几何体不是多边形
if(selectGeometry->type()!=QGis::Polygon){
return;
}
QgsGeometry selectGeomTrans(*selectGeometry);
//设定选择几何体的坐标系和图层的坐标系一致
if(mCanvas->mapRenderer()->hasCrsTransformEnabled()){
try{
//将地图绘板坐标系变换到图层坐标系
QgsCoordinateTransform ct(mCanvas->mapRenderer()->destinationSrs(),pLayer->crs());
//设定几何体的坐标系和图层坐标系一致
selectGeomTrans.transform(ct);
}
//对于异常点抛出异常
catch(QgsCsException &cse){
Q_UNUSED(cse);
//catch exception for 'invalid' point and leave existing selection unchanged
QMessageBox::warning(mCanvas, QObject::tr("CRS Exception"),
QObject::tr( "Selection extends beyond layer's coordinate system." ) );
return;
}
}
//设置光标
//QApplication::setOverrideCursor(Qt::WaitCursor);
//选择和选择几何体相交或在几何体内部的特征
pLayer->select(QgsAttributeList(),selectGeomTrans.boundingBox(),true,true);
int nh=pLayer->selectedFeatureCount();
QgsFeatureIds newSelectedFeatures;
QgsFeature f;
;
//得到当前选择的特征
while(pLayer->nextFeature(f)){
p++;
QgsGeometry* g=f.geometry();
//选择的特征是否包含在选择几何体的内部
//如果g包含selectGeomTrans,返回true
if(!g->contains(&selectGeomTrans)){
continue;
}
//存储符合条件图层特征id
newSelectedFeatures.insert(f.id());
}
QgsFeatureIds layerSelectedFeatures;
//如果按下ctrl键,可以选择多个特征
if(doDifference){
layerSelectedFeatures=pLayer->selectedFeaturesIds();
QgsFeatureIds::const_iterator i = newSelectedFeatures.constEnd();
while( i != newSelectedFeatures.constBegin()){
--i;
if( layerSelectedFeatures.contains( *i ) )
{
layerSelectedFeatures.remove( *i );
}
else
{
layerSelectedFeatures.insert( *i );
}
}
}
else{
layerSelectedFeatures=newSelectedFeatures;
}
//设定选择的特征
pLayer->setSelectedFeatures(layerSelectedFeatures);
//QApplication::restoreOverrideCursor();
}
//设定工具状态
void QgsMapToolSelect::SetEnable(bool flag)
{
StatusFlag=flag;
if(StatusFlag){
mCursor=Qt::CrossCursor;
}
else{
mCursor=Qt::ArrowCursor;
}
}
IdentifyResultDlg * QgsMapToolSelect::ResultDlg()
{
if (mIdentifyResultDlg == NULL)
{
mIdentifyResultDlg = new IdentifyResultDlg;
}
return mIdentifyResultDlg;
}
//得到选择的要素的属性信息
QList<QMap<QString, QString>> QgsMapToolSelect::GetAttributeValue( QgsVectorLayer *layer, QgsFeatureIds selectedFIds )
{
// QStringList strAttribute;
QMap<QString, QString> featureValue;
QList<QMap<QString, QString>> featureValues;
, nFeatureCount = , nFieldsCount = ;
if (layer == NULL)
{
return featureValues;
}
QgsFeatureList featurelist = layer->selectedFeatures();
nFeatureCount = featurelist.size();
QgsFeature feature;
QString fieldName, fieldValue;
// vector<QgsField> myFields = layer->fields();
; i < nFeatureCount; i++)
{
feature = featurelist.at(i);
const QgsAttributeMap &attributes = feature.attributeMap();
nFieldsCount = attributes.count();
const QgsFieldMap &fields = layer->pendingFields();//从图层得到字段信息
QgsField field;
; j < nFieldsCount; j++)
{
field = fields[j];
fieldName = field.name();
fieldValue = attributes[j].toString();
featureValue.insert(fieldName, fieldValue);
}
featureValues.push_back(featureValue);
}
return featureValues;
}
void QgsMapToolSelect::setShowFlag( bool flag )
{
isShowFlag = flag;
}
查询得到的数据显示在对话框:
IdentifyResultDlg对话框是为了显示查询得到的结果。它的定义:
class IdentifyResultDlg : public QDialog
{
Q_OBJECT
public:
IdentifyResultDlg(QWidget *parent = );
~IdentifyResultDlg();
void InitialDlg();
void InitialData(QList<QMap<QString, QString>>);
private:
Ui::IdentifyResultDlg ui;
QStandardItemModel *fieldmodel;
};
IdentifyResultDlg具体实现:
#include "identifyresultdlg.h"
IdentifyResultDlg::IdentifyResultDlg(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
QStringList lists;
InitialDlg();
}
IdentifyResultDlg::~IdentifyResultDlg()
{
}
void IdentifyResultDlg::InitialDlg()
{
this->setWindowTitle(tr("查询要素属性信息"));
fieldmodel = new QStandardItemModel();
fieldmodel->setColumnCount();
ui.tableView->setModel(fieldmodel);
ui.tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);//设置表格不可编辑
ui.tableView->verticalHeader()->hide(); //列头不显示
ui.tableView->setSelectionBehavior(QAbstractItemView::SelectRows);//选择整行高亮
setWindowFlags(Qt::WindowStaysOnTopHint);//使窗口置顶
, );
}
//将数据显示在表格中
void IdentifyResultDlg::InitialData( QList<QMap<QString, QString>> datas)
{
fieldmodel->clear();//注意:在clear之后,表头名称也被清除了,需再设置表头
fieldmodel->setHorizontalHeaderItem(, new QStandardItem(QObject::tr("属性名称")));
fieldmodel->setHorizontalHeaderItem(, new QStandardItem(QObject::tr("属性值")));
QString name, value;
QMap<QString,QString>::iterator it;
;
; i < datas.count(); i ++)
{
QMap<QString,QString> data = datas.at(i);
;
; it != data.end(), j < data.count(); ++it, ++j)
{
int index = i * data.count() +j;
fieldmodel->setItem(index, , new QStandardItem(it.key()));
if (it.value() == NULL)
{
it.value() = ";
}
fieldmodel->setItem(index, , new QStandardItem(it.value()));
fieldmodel->item(index, )->setTextAlignment(Qt::AlignCenter);
fieldmodel->item(index, )->setTextAlignment(Qt::AlignCenter);
)
{
fieldmodel->item(index, )->setBackground(QBrush(QColor(, , )));
fieldmodel->item(index, )->setBackground(QBrush(QColor(, , )));
}
}
}
}
查询一个要素和多个要素的结果如下图所示:


注意:可能中文字段显示乱码,解决方法:
在操作shp之前,添加这句就可以了:
CPLSetConfigOption("SHAPE_ENCODING","");
QGis(三)查询矢量图层的要素属性字段值(转载)的更多相关文章
- Qt+QGIS二次开发:自定义类实现查询矢量数据的属性字段值(图查属性)
在GIS领域,有两种重要的查询操作,图查属性和属性查图. 本文主要介绍如何在QGIS中通过从QgsMapToolIdentify中派生自定义类实现查询矢量数据的属性字段值(图查属性). 重点参考资料: ...
- OpenLayers在多个矢量图层编辑要素
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head ...
- ArcMap10.1修改要素属性字段
ArcMap10.1修改要素属性字段 问题描述:在ArcMap10.1中编辑要素属性表时,遇到输入字段值的长度超过字段最大长度时,ArcMap会抛出“基础DBMS错误[ORA-12899:value ...
- [ArcGIS API for JavaScript 4.8] Sample Code-Popups-1-popupTemplate的概念和popup中属性字段值的多种表现形式
[官方文档:https://developers.arcgis.com/javascript/latest/sample-code/intro-popuptemplate/index.html] 一. ...
- openlayers3 在地图上叠加WFS查询矢量图层
随着终端设备计算能力的加强,用户在使用地图的时候也须要越来越多的交互效果. 比方如今非常火的室内导航,为了获得好的用户体验,就须要当用户单击某一商店的时候该商店的颜色能对应的变化.这就须要叠加矢量图层 ...
- datagridcolumn单元格怎么显示查询到的某个表的字段值(字段值可能为多个)
例如,在之前做的项目中,查询mhz_xckcr表,select出某个业务的现场勘察人信息,select出的现场勘察人姓名(可能有多个)要在前台datagrid的一个datagridcolmn单元格显示 ...
- Dynamics CRM2016 Web API之更新记录的单个属性字段值
在web api中提供了对单个属性的更新接口,这和查询中查询单个属性类似,对这个接口我个人也是比较喜欢的. var id = "{D1E50347-86EB-E511-9414-ADA183 ...
- Arcpy按属性(字段值)不同将shp分割为多个独立shp_适用点线面矢量
利用代码可以进行批量处理,安装有10.5及以上版本ArcGIS可以使用工具Split by attributes完成上述任务 # -*- coding: utf-8 -*- # Import syst ...
- json转化的时候如何忽略某些属性字段值
一.有时候在将对象或list对象转化为json的时候,我们可能不需要所有的属性值,这就需要我们去过滤掉这些属性了 我下面说两种比较流行的json包如何来忽略某些属性值 二. 使用jaskson包 1. ...
随机推荐
- Ubuntu新建用户
新建用户的命令是useradd,修改密码是passwd,如下: sudo useradd linc sudo passwd linc 但是问题出现了,home目录下并没有相对应的linc目录. 原来u ...
- AngularJS中的$http.post与jQuery.post的区别
原文:http://my.oschina.net/tommyfok/blog/287748 很多时候我们需要用ajax提交post数据,angularjs与jq类似,也有封装好的post. 但是jQu ...
- js判断是否是正整数,js判断是否是数字
//判断字符串是否为数字 function checkRate(input) { var re = /^[0-9]+.?[0-9]*$/; if (!re.test(input.rate.value) ...
- Android -----paint cap join 理解 ,paint画笔形状设置
引自:http://www.2cto.com/kf/201501/370215.html 网上查了很多资料,对paint的里面的枚举类cap join讲的不是很透彻.在这里自己做一个比较深入的研究. ...
- 2015浙江财经大学ACM有奖周赛(一) 题解报告
2015浙江财经大学ACM有奖周赛(一) 题解报告 命题:丽丽&&黑鸡 这是命题者原话. 题目涉及的知识面比较广泛,有深度优先搜索.广度优先搜索.数学题.几何题.贪心算法.枚举.二进制 ...
- urllib2修改header
python网络访问的标准模块 urllib与urllib2并不是升级版的关系,具体可见谷歌文章:difference between urllib and urllib2urllib2的官方文档:h ...
- c# winform 点击按钮切换tabcontrol标签
this.tabControl1.TabPages.Remove(tabPage1); this.tabControl1.TabPages.Remove(tabPage2); this.tabCont ...
- MyBatis部分细节归档
1. xml中如果要使用到特殊的字符,比如> 或者< 等,使用 <![CDATA[<]> 进行包裹,避免解析XML的时候出错. 2. 后续还有内容,待总结.
- 小米1S iptables禁止443端口
shell@android:/system/bin # ./iptables -A INPUT -p tcp --dport 443 -j DROP./iptables -A INPUT -p tcp ...
- nginx 红黑树详解
1 介绍 这部分终于整理完了,太耗时间了,留下来备忘吧! 之前看STL源码时,只是研究了红黑树的插入部分.在stl源码剖析的书中,也没有涉及到删除操作的分析,这次对删除操作也进行了详细的研究, 并且还 ...