摘要: qgis的资料比较少,能找到的资料就那么几篇基本的加载图层之类的,最主要还是参考qgis本身的源码和其api文档。 qgis程序是C++和qt平台编译出来的可执行文件。 其中MapCanvas保存了一个指针指向当前的tool,tool里面有各种响应鼠标等事件。...
qgis的资料比较少,能找到的资料就那么几篇基本的加载图层之类的,最主要还是参考qgis本身的源码和其api文档。
qgis程序是C++和qt平台编译出来的可执行文件。
其中MapCanvas保存了一个指针指向当前的tool,tool里面有各种响应鼠标等事件。
MapCanvas中的响应系统鼠标事件,调用tool的事件
其中鼠标Middle单击事件,被定义为pan(tool)的事件
tool可以setAction,也可以设置按键。(效果应该等同于Action的trigger信号绑定MapCanvas,设置mapcanvas的当前tool。)还可以设置cursor设置鼠标的形状(手型)
所以在知道qgis的tool功能的基础上找到源码中的selecttool,将selecttool移植到自己的程序中。
注意:这移植的过程中,也出现了一些问题,以为可以调用qgisapp的库进行移植,但是移植过程中出现了一系列的错误。所以最后还是只调用qgis的核心库
//QgsVectorLayer* vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( mCanvas ); //这一行的功能为选择当前的矢量图层,改成如下代码: QgsVectorLayer* vlayer = NULL; if ( !canvas->currentLayer() || ( vlayer = qobject_cast( canvas->currentLayer() ) ) == NULL ) { QMessageBoox::information(...);} if ( vlayer == NULL ) { return; } QgsRubberBand *rubberBand = new QgsRubberBand( mCanvas, QGis::Polygon ); QRect selectRect( 0, 0, 0, 0 ); //QgsMapToolSelectUtils::expandSelectRectangle( selectRect, vlayer, e->pos() ); //这行代码的意义在于将点的范围扩大。 int boxSize = 0; if ( vlayer->geometryType() != QGis::Polygon ) { //if point or line use an artificial bounding box of 10x10 pixels //to aid the user to click on a feature accurately boxSize = 5; } else { //otherwise just use the click point for polys boxSize = 1; } selectRect.setLeft( point.x() - boxSize ); selectRect.setRight( point.x() + boxSize ); selectRect.setTop( point.y() - boxSize ); selectRect.setBottom( point.y() + boxSize ); // // QgsMapToolSelectUtils::setRubberBand( mCanvas, selectRect, &rubberBand ); const QgsMapToPixel* transform = canvas->getCoordinateTransform(); QgsPoint ll = transform->toMapCoordinates( selectRect.left(), selectRect.bottom() ); QgsPoint ur = transform->toMapCoordinates( selectRect.right(), selectRect.top() ); if ( rubberBand ) { rubberBand->reset( QGis::Polygon ); rubberBand->addPoint( ll, false ); rubberBand->addPoint( QgsPoint( ur.x(), ll.y() ), false ); rubberBand->addPoint( ur, false ); rubberBand->addPoint( QgsPoint( ll.x(), ur.y() ), true ); } QgsGeometry* selectGeom = rubberBand.asGeometry(); bool doDifference = e->modifiers() & Qt::ControlModifier ? true : false; // QgsMapToolSelectUtils::setSelectFeatures( mCanvas, selectGeom, false, doDifference, true ); //这一行才是选择的功能 if ( selectGeometry->type() != QGis::Polygon ) { return; } QgsVectorLayer* vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( canvas ); if ( vlayer == NULL ) { return; } // toLayerCoordinates will throw an exception for any 'invalid' points in // the rubber band. // For example, if you project a world map onto a globe using EPSG 2163 // and then click somewhere off the globe, an exception will be thrown. QgsGeometry selectGeomTrans( *selectGeometry ); if ( canvas->mapSettings().hasCrsTransformEnabled() ) { try { QgsCoordinateTransform ct( canvas->mapSettings().destinationCrs(), vlayer->crs() ); selectGeomTrans.transform( ct ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); // catch exception for 'invalid' point and leave existing selection unchanged // QgsLogger::warning( "Caught CRS exception " + QString( __FILE__ ) + ": " + QString::number( __LINE__ ) ); QMessageBox::warning( canvas, QObject::tr( "CRS Exception" ), QObject::tr( "Selection extends beyond layer's coordinate system." ) ); return; } } QApplication::setOverrideCursor( Qt::WaitCursor ); QgsDebugMsg( "Selection layer: " + vlayer->name() ); QgsDebugMsg( "Selection polygon: " + selectGeomTrans.exportToWkt() ); QgsDebugMsg( "doContains: " + QString( doContains ? "T" : "F" ) ); QgsDebugMsg( "doDifference: " + QString( doDifference ? "T" : "F" ) ); QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectGeomTrans.boundingBox() ).setFlags( QgsFeatureRequest::ExactIntersect ).setSubsetOfAttributes( QgsAttributeList() ) ); QgsFeatureIds newSelectedFeatures; QgsFeature f; QgsFeatureId closestFeatureId = 0; bool foundSingleFeature = false; double closestFeatureDist = std::numeric_limits ::max(); while ( fit.nextFeature( f ) ) { QgsGeometry* g = f.geometry(); //if ( doContains ) // { if ( !selectGeomTrans.contains( g ) ) continue; // } // else // { // if ( !selectGeomTrans.intersects( g ) ) // continue; // } //if ( singleSelect ) // { foundSingleFeature = true; double distance = g->distance( selectGeomTrans ); if ( distance <= closestFeatureDist ) { closestFeatureDist = distance; closestFeatureId = f.id(); } // } // else // { // newSelectedFeatures.insert( f.id() ); // } } if ( /*singleSelect &&*/ foundSingleFeature ) { newSelectedFeatures.insert( closestFeatureId ); } QgsDebugMsg( "Number of new selected features: " + QString::number( newSelectedFeatures.size() ) ); if ( doDifference ) { QgsFeatureIds layerSelectedFeatures = vlayer->selectedFeaturesIds(); QgsFeatureIds selectedFeatures; QgsFeatureIds deselectedFeatures; QgsFeatureIds::const_iterator i = newSelectedFeatures.constEnd(); while ( i != newSelectedFeatures.constBegin() ) { --i; if ( layerSelectedFeatures.contains( *i ) ) { deselectedFeatures.insert( *i ); } else { selectedFeatures.insert( *i ); } } vlayer->modifySelection( selectedFeatures, deselectedFeatures ); } else { vlayer->setSelectedFeatures( newSelectedFeatures ); } QApplication::restoreOverrideCursor(); delete selectGeom; rubberBand.reset( QGis::Polygon );