前言
前几篇文章分别介绍了qgis二次开发的
在显示GIS数据之前,需要首先介绍一下map canvas,毕竟在将颜料(GIS地图等数据)画在画布(map canvas)之前,首先要创建画布(map canvas)。
- 说明:文章中的示例代码均来自开源项目qgis_cpp_api_apps
Map canvas
QGis软件中的Map canvas
- 官方文档training_manual 有一节Navigating the Map Canvas专门讲述了Map Canvas
-
下图空白区域左侧为图层树(Layer tree),右侧为Map Canvas
代码添加Map canvas
Map canvas is a class for displaying all GIS data types on a canvas.
QgsMapCanvas
是Map canvas,类的详细内容见文档-
QgsMapCanvas
本质是一个QGraphicsView
,QGraphicsView
是Qt Graphics View Framework框架的一个类,Graphics View Framework
是Qt提供的一个用于管理大量2D图形项目并与之交互的框架。
-
QGraphicsView
提供了视图,相当于画布 -
QGraphicsItem
图形类的基类,可以显示在canvas的组件,QgsMapCanvasItem
是该类的子类 -
QGraphicsScene
用于管理item
-
Map Canvas创建和显示
- Map Canvas创建代码如下
void ll_qgis_base_lib::initialize(QMainWindow *mainWindow)
{
mMainWindow = mainWindow;
mMapCanvas = new QgsMapCanvas;
mMapCanvas->enableAntiAliasing(true);
mMapCanvas->setCachingEnabled(true);
mMapCanvas->setCanvasColor(QColor(255,255,255));
mMapCanvas->setVisible(true);
initLayerTreeView();
initMaptools();
}
-
ll_qgis_base_lib
类是qgis_cpp_api_apps项目的一个库,由于Map canvas和Layer tree很通用,所以将这两个放在库中 - 将
mMapCanvas
添加到父Widget即可显示Map canvas
void MainWindow::initStackwidgetPageCanvas()
{
auto gridLayout = new QGridLayout;
gridLayout->addWidget((QWidget*)mApp->mapCanvas());
ui->page_canvas->setLayout(gridLayout);
addDockWidget(Qt::LeftDockWidgetArea,mApp->layerTreeDock());
}
QGis中的QGraphicsItem
- Measure功能使用了
QgsRubberBand
类,上图中的三角形就是用QgsRubberBand
类绘制的
二次开发中的Item
类
QgsMapCanvasItem
是一个抽象类,用于放置在地图画布上的项目。-
类
QgsRubberband
类是一个用于在地图上绘制临时特征(例如数字化线条)的类。类图如下
如下代码实现在图层上画三角形
void MainWindow::rubberBandPolygonSlot()
{
//添加shapefile
QString filename = QStringLiteral("maps/shapefile/protected_areas.shp");
QFileInfo ff(filename);
mApp->addVectorLayer(filename,ff.baseName());
zoomToFirstLayer<QgsVectorLayer*>();
//定义三个点
QgsPointXY point1(20.34013,-33.90453);
QgsPointXY point2(20.49744,-33.91126);
QgsPointXY point3(20.41396,-33.93079);
//新建PolygonGeometry类型的RubberBand
mRubberBandPolygon = new QgsRubberBand(mApp->mapCanvas(),QgsWkbTypes::PolygonGeometry);
//添加三个点
mRubberBandPolygon->addPoint(point1);
mRubberBandPolygon->addPoint(point2);
mRubberBandPolygon->addPoint(point3);
//设置线宽颜色等属性
mRubberBandPolygon->setWidth(4);
mRubberBandPolygon->setColor(QColor(222,155,67));
mRubberBandPoint = new QgsRubberBand(mApp->mapCanvas(),QgsWkbTypes::PointGeometry);
mRubberBandPoint->addPoint(point1);
mRubberBandPoint->addPoint(point2);
mRubberBandPoint->addPoint(point3);
mRubberBandPoint->setWidth(6);
mRubberBandPoint->setColor(QColor(222,155,67));
mRubberBandPolygon->show();
mRubberBandPoint->show();
}
- 以下代码实现删除
QgsGraphicsItem
if(mVertexMarker)
mApp->mapCanvas()->scene()->removeItem(mVertexMarker);
Layer Tree
QGis软件中的Layer Tree
- Layer Tree用于管理图层
- Layer Tree和Map canvas建立连接,可以对图层进行操作
代码实现layer tree
- 代码如下
void ll_qgis_base_lib::initLayerTreeView()
{
//添加DockWidget作为图层树的容器
mLayerTreeDock = new QgsDockWidget(tr("Layer Tree"));
mLayerTreeDock->setObjectName( QStringLiteral( "Layers" ) );
mLayerTreeDock->setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea );
//创建Model
QgsLayerTreeModel* model = new QgsLayerTreeModel(QgsProject::instance()->layerTreeRoot(),this);
model->setFlag( QgsLayerTreeModel::AllowNodeReorder );
model->setFlag( QgsLayerTreeModel::AllowNodeRename );
model->setFlag( QgsLayerTreeModel::AllowNodeChangeVisibility );
model->setFlag( QgsLayerTreeModel::ShowLegendAsTree );
model->setFlag( QgsLayerTreeModel::UseEmbeddedWidgets );
model->setFlag( QgsLayerTreeModel::UseTextFormatting );
model->setAutoCollapseLegendNodes( 10 );
//创建View,mLayerTreeView会在库外使用,所以需要添加getter方法,
mLayerTreeView = new QgsLayerTreeView();
mLayerTreeView->setModel(model);
//Map Canvas和Layer Tree View建立联系,这样通过QgsProject::instance()->addMapLayer添加图层后,会自动添加在图层树以及会在canvas渲染图层
mLayerTreeMapCanvasBridge = new QgsLayerTreeMapCanvasBridge(QgsProject::instance()->layerTreeRoot(),mMapCanvas,this);
connect( mLayerTreeMapCanvasBridge, &QgsLayerTreeMapCanvasBridge::canvasLayersChanged, mMapCanvas, &QgsMapCanvas::setLayers );
//Layer Tree View右键菜单实现
mLayerTreeView->setMenuProvider(new ll_qgis_base_layertreeview_menu(mMainWindow,mLayerTreeView,mMapCanvas));
connect(QgsProject::instance()->layerTreeRegistryBridge(),SIGNAL(addedLayersToLayerTree(QList<QgsMapLayer*>)),
this,SLOT(slot_autoSelectAddedLayer(QList<QgsMapLayer*>)));
}
- 主要涉及了以下类
QgsDockWidget
,QgsLayerTreeModel
,QgsLayerTreeView
,QgsLayerTreeMapCanvasBridge
-
QgsDockWidget
是一个Qt Dock Widget,用于显示图层树 -
QgsLayerTreeView
和QgsLayerTreeModel
实现了树的功能 -
QgsLayerTreeMapCanvasBridge
类负责从图层树中更新QgsMapCanvas
的图层
QgsProject(项目管理)
QGis的项目可以保存为项目文档,后缀名为“qgz”或“qgs”。在QGIS 3以前,只能通过“qgs”文件保存项目。“qgs”文件的本质是存储图层的信息等的XML文件。在QGIS 3以后,“qgz”格式采用ZIP压缩方法,不仅包含“qgs”文件,还包括附属数据库(Auxiliary Storage)文件(后缀名为“qgd”)。自QGIS 3.2以来,“qgz”文件成为QGIS项目的默认存储格式,本书也使用“qgz”文件存储QGIS项目。
QGis软件中的项目管理
-
新建项目,在Project菜单中可以新建一个空工程
-
保存项目 可以选择项目名称和位置
代码实现
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
QgsProject is available both as a singleton (QgsProject::instance()) and for use as standalone objects. The QGIS project singleton always gives access to the canonical project reference open within the main QGIS application.
- 类
QgsProject
代表QGis中的一个项目,包含项目管理、图层管理以及其他功能,QgsProject
的详细内容见官方文档。 -
QgsProject
是一个单例类,通过方法QgsProject::instance()
即可调用其方法,以下是QgsProject
的一些常用函数 -
QgsProject
的最常用的功能是添加图层,调用QgsProject::instance()->addMapLayer(vecLayer);
后会在Map Canvas显示,也会添加到Layer tree中,如下代码添加一个shape文件
void MainWindow::addShpSlot()
{
QString filename = QStringLiteral("maps/shapefile/protected_areas.shp");
QFileInfo ff(filename);
//创建图层
QgsVectorLayer* vecLayer = new QgsVectorLayer(filename,ff.baseName(),"ogr");
if(!vecLayer->isValid())
{
QMessageBox::critical(this,tr("error"),tr("invalid layer"));
return;
}
QgsProject::instance()->addMapLayer(vecLayer);
zoomToFirstLayer<QgsVectorLayer*>();
}
- 以下是
QgsProject
的常用函数
//读取项目文件
bool read (const QString &filename, Qgis::ProjectReadFlags flags=Qgis::ProjectReadFlags())
bool read (Qgis::ProjectReadFlags flags=Qgis::ProjectReadFlags())
//保存项目文件
bool write ()
bool write (const QString &filename)
//添加单个图层
QgsMapLayer * addMapLayer (QgsMapLayer *mapLayer, bool addToLegend=true, bool takeOwnership=true)
//添加多个图层
QList< QgsMapLayer * > addMapLayers (const QList< QgsMapLayer * > &mapLayers, bool addToLegend=true, bool takeOwnership=true)
Q_INVOKABLE QgsMapLayer *mapLayer (const QString &layerId) const
template<class T >
T mapLayer (const QString &layerId) const
QMap< QString, QgsMapLayer * > mapLayers (const bool validOnly=false) const
QList< QgsMapLayer * > mapLayersByShortName (const QString &shortName) const
template<typename T >
QVector< T > mapLayersByShortName (const QString &shortName) const
void removeAllMapLayers ()
void removeMapLayer (const QString &layerId)
void removeMapLayer (QgsMapLayer *layer)
void removeMapLayers (const QList< QgsMapLayer * > &layers)
void removeMapLayers (const QStringList &layerIds)
总结
-
QgsMapCanvas
作为视图类提供了绘制的画布 -
QgsMapCanvasItem
可以绘制在画布上的Item -
QgsProject
图层管理,尤其在添加图层时常用 - 了解了这几个类,就可以学习如何显示GIS数据了