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. ...
随机推荐
- webpy
url处理 对于一个站点来说,URL 的组织是最重要的一个部分,因为这是用户看得到的部分,而且直接影响到站点是如何工作的,在著名的站点如:del.icio.us ,其URLs 甚至是网页界面的一部分. ...
- 改写BlogEngine.NET头像上传实现方式(使用baidu.flash.avatarMaker)
baidu.flash.avatarMaker 需要资源文件和javascript类库: 1 2 3 4 5 6 7 需要应用的script library: <scriptsrc=" ...
- 【转】使IFRAME在iOS设备上支持滚动
原文链接: Scroll IFRAMEs on iOS原文日期: 2014年07月02日 翻译日期: 2014年07月10日翻译人员: 铁锚 很长时间以来, iOS设备上Safari中超出边界的元素将 ...
- 手机电话号码吉凶查询原理及ASP算法源码 转
随着手机的快速普及,越来越多的人都在使用手机,而号码的挑选也是用户越来越关心的事情.虽然号码只是个代号而已,但几千年的传统积淀仍给号码赋予其各种含义,至于号码的吉凶也是见仁见智的一种个人喜好问题,或许 ...
- ie用document.getElementsByName获取不到
document.getElementsByName('someName') 返回一个节点列表(数组) 注意:在IE下有些节点是没有name 属性的,就是用document.getElementsBy ...
- 使用MyEclipse构建MAVEN项目 - 我的漫漫程序之旅 - BlogJava
body { font-family: Microsoft YaHei UI,"Microsoft YaHei", Georgia,Helvetica,Arial,sans-ser ...
- HDU 5531 Rebuild
2015 ACM/ICPC 长春现场赛 E题 三分. 如果节点个数是奇数,那么直接列方程可以求解,因为,如果第一个圆半径变大,必然导致最后一个圆的半径变大, 所以,节点是奇数的时候,要么无解,要么只有 ...
- 网页解析的全过程(输入url到展示页面)
1.用户输入网址,浏览器发起DNS查询请求 用户访问网页,DNS服务器(域名解析系统)会根据用户提供的域名查找对应的IP地址. 域名解析服务器是基于UDP协议实现的一个应用程序,通常通过监听53端口来 ...
- python之路:进阶篇
> ) { ; } printf(;} print i >>> >>> == : name == == ...
- iOS之PCH文件
在Xcode6之前,创建一个新工程xcode会在Supporting files文件夹下面自动创建一个“工程名-Prefix.pch”文件,也是一个头文件,pch头文件的内容能被项目中的其他所有源文件 ...