QGis(三)查询矢量图层的要素属性字段值

QGis(三)查询矢量图层的要素属性字段值

分类:QGis二次开发

当加载一个矢量图层后,如果要查看要素的属性字段值,则需要实现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);if ( mainMapCanvas->layer(0)->type() == QgsMapLayer::RasterLayer){return;}QgsVectorLayer *pLayer=(QgsVectorLayer *)mainMapCanvas->layer(0);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(0,0,0,0); //设置鼠标位置区域 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){ int boxSize=0; //如果图层不是面图元类型 if(pLayer->geometryType()!=QGis::Polygon){boxSize=5; } else{boxSize=1; } //设置选择区域 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 unchangedQMessageBox::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;int closestFeatureId=0;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;//计算出最靠近选择几何体特征的idclosestFeatureId=f.id();}}else{ //存储符合要求的特征idnewSelectedFeatures.insert(f.id());} } //确定和选择几何体最靠近特征的id if(singleSelect && foundSingleFeature){newSelectedFeatures.insert(closestFeatureId); } //如果按下ctrl键,选择多个特征 if(doDifference){//得到所有选择特征的idlayerSelectedFeatures=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 unchangedQMessageBox::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;int p=0;//得到当前选择的特征while(pLayer->nextFeature(f)){p++;QgsGeometry* g=f.geometry();//选择的特征是否包含在选择几何体的内部//如果g包含selectGeomTrans,,返回trueif(!g->contains(&selectGeomTrans)){continue;}//存储符合条件图层特征idnewSelectedFeatures.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;int i = 0, nFeatureCount = 0, nFieldsCount = 0;if (layer == NULL){return featureValues;}QgsFeatureList featurelist = layer->selectedFeatures();nFeatureCount = featurelist.size();QgsFeature feature;QString fieldName, fieldValue;//vector<QgsField> myFields = layer->fields();for (i = 0; i < nFeatureCount; i++){feature = featurelist.at(i);const QgsAttributeMap &attributes = feature.attributeMap();nFieldsCount = attributes.count();const QgsFieldMap &fields = layer->pendingFields();//从图层得到字段信息QgsField field;for(int j = 0; 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_OBJECTpublic:IdentifyResultDlg(QWidget *parent = 0);~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(2);ui.tableView->setModel(fieldmodel); ui.tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);//设置表格不可编辑ui.tableView->verticalHeader()->hide(); //列头不显示ui.tableView->setSelectionBehavior(QAbstractItemView::SelectRows);//选择整行高亮setWindowFlags(Qt::WindowStaysOnTopHint);//使窗口置顶this->resize( 240, 300);}//将数据显示在表格中void IdentifyResultDlg::InitialData( QList<QMap<QString, QString>> datas){fieldmodel->clear();//注意:在clear之后,表头名称也被清除了,需再设置表头fieldmodel->setHorizontalHeaderItem(0, new QStandardItem(QObject::tr("属性名称")));fieldmodel->setHorizontalHeaderItem(1, new QStandardItem(QObject::tr("属性值")));QString name, value;QMap<QString,QString>::iterator it;int i = 0;for (i = 0; i < datas.count(); i ++){QMap<QString,QString> data = datas.at(i);int j = 0;for (it = data.begin(), j = 0; it != data.end(), j < data.count(); ++it, ++j){int index = i * data.count() +j;fieldmodel->setItem(index, 0, new QStandardItem(it.key()));if (it.value() == NULL){it.value() = "0";}fieldmodel->setItem(index, 1, new QStandardItem(it.value()));fieldmodel->item(index, 0)->setTextAlignment(Qt::AlignCenter);fieldmodel->item(index, 1)->setTextAlignment(Qt::AlignCenter);if ( j%(data.count()) == 0){fieldmodel->item(index, 0)->setBackground(QBrush(QColor(188, 188, 188)));fieldmodel->item(index, 1)->setBackground(QBrush(QColor(188, 188, 188)));}}}}

查询一个要素和多个要素的结果如下图所示:

用开怀的笑容去迎接每一个黎明,

QGis(三)查询矢量图层的要素属性字段值

相关文章:

你感兴趣的文章:

标签云: