4. qgis c++二次开发 map canvas介绍

前言

前几篇文章分别介绍了qgis二次开发的

在显示GIS数据之前,需要首先介绍一下map canvas,毕竟在将颜料(GIS地图等数据)画在画布(map canvas)之前,首先要创建画布(map canvas)。

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本质是一个QGraphicsViewQGraphicsView是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,用于显示图层树
  • QgsLayerTreeViewQgsLayerTreeModel实现了树的功能
  • 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数据了
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雷动软件工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值