手动选择显示_QGIS 二次开发笔记(2)——显示图层

本文介绍QGIS二次开发如何显示图层,重点是加载ESRI Shapefile数据源。通过添加地图框、提升组件类型或手动创建,实现图层的加载与显示。并探讨了图层树的实现及其在布局管理中的作用。
摘要由CSDN通过智能技术生成
本文使用 Zhihu On VSCode 创作并发布

基于 QGIS 二次开发,最首要的功能就是显示图层。这是个看似非常简单的功能,但是在 QGIS 中写了非常复杂的代码,以支持各种数据源。
但是我们在二次开发中,一般不会支持那么多的数据源。这篇博客首先以 ESRI Shapefile 数据源为例,展示加载图层的过程。

博客以创建好的工程开始,创建工程的过程网上资料很多,这里就不再赘述了。

添加地图框

要想显示图层,首先要有一个显示图层的地方。在 QGIS SDK 中,使用类 QgsMapCanvas 显示地图。这个类需要 QT 中的 svg 组件,即

# QgsSdkApp.pro
QT += core gui xml svg

如果我们想在 QMainWindow 派生类(我的工程中创建的类名是 QgsSdkApp ,以后直接用这个名称)添加一个 QgsMapCanvas 类型的组件,
有以下三种方法:

  1. 添加插件的方式:在 QT Designer 中添加插件,在 QT Designer 中绘制(我没有实现成功,理论上可以)
  2. 提升类型的方式:在 QT Designer 中使用“提升”功能,将 QWidget 组件提升为 QgsMapCanvas 类型
  3. 手动创建的方式:在 QgsSdkApp.cpp 中手动创建 QgsMapCanvas 类型的对象,添加到窗口中

下面一一展示。

提升类型的方式

选择一个组件,右键单击之后,单击“提升为”按钮,可以弹出提升窗口部件的对话框。

1bcedfcf78bd530d4d53789b2789e294.png
打开“提升的窗口部件”对话框的方法

d5eac7a11d93f1f9f796d50076ea50d7.png
提升的窗口部件对话框

上面这个对话框,现在 1 所示的位置输入要提升的类型的名称,然后点击 2 位置上的按钮,在上面的列表上选中刚刚添加的提升类型,
点击 3 位置上的按钮,即可将该组件提升为指定的类型(即 QgsMapCanvas 类型)。

然后,在 cpp 文件中已经可以访问到这个类型的组件了。

手动创建的方式

手动创建的方式就是在窗口类的构造函数中,构造一个 QgsMapCanvas 类型的对象,然后添加到窗口上。
这种情况下和其他在 QT 中手动创建对象没有差别,和其他一样处理即可。

添加图层

添加了地图框(在类内使用一个指针 mMapCanvas ,指向这个地图框)之后,下面就可以来添加图层了。
首先以 ESRI Shapefile 为例,介绍一下添加 QgsVectorLayer 的基本方法。

添加矢量图层的方法

在 QgsSdkApp.ui 中可以添加一个 action ,并拖到工具栏上创建工具按钮。点击这个按钮后开始添加图层。
这个过程网上有很多教程,这里就不再赘述了。

如果要添加 ESRI Shapefile 图层,我们需要先选择这个文件。我们可以直接弹出一个文件选择对话框。
我们以选择的文件路径作为数据源的路径,文件名(不含扩展名)为图层名称。

void QgsSdkApp::on_actionShp_Layer_triggered()
{
    
    QString filePath = QFileDialog::getOpenFileName(this, tr("Open ESRI Shapefile"), tr(""), tr("ESRI Shapefile (*.shp)"));
    QFileInfo fileInfo(filePath);
    if (fileInfo.exists())
    {
    
        QString fileName = fileInfo.baseName();
        addVectorLayer(filePath, fileName, "ogr");
    }
}

创建 addVectorLayer() 函数,用于添加图层。我们可以以一种简单的方式添加图层,即直接创建 QgsVectorLayer 对象,并保存到一个列表(mMapLayerList)里。
然后让地图框加载这个列表,即可显示地图。

QgsVectorLayer *QgsSdkApp::addVectorLayer(const QString &vectorLayerPath, const QString &name, const QString &providerKey, bool guiWarning)
{
    
    QgsVectorLayer* vectorLayer = new QgsVectorLayer(uri, layerName, providerKey);
    mMapLayerList.append(vectorLayer);
    mMapCanvas->setLayers(mMapLayerList);
    if (mMapLayerList.size() == 1)
    {
    
        QgsMapLayer* firstLayer = mMapLayerList.first();
        QgsRectangle extent = mMapCanvas->mapSettings().layerExtentToOutputExtent(firstLayer, firstLayer->extent());
        mMapCanvas->setExtent(extent);
    }
    mMapCanvas->refresh();
}

这个函数中除了添加了地图,同时也限制了地图框地显示范围,即设置为第一个图层地显示范围。最后对地图进行了刷新。但是这种方式会遇到很多问题:

  1. 如果将来要设计 Layout ,那么这个地图框的内容无法同步到 Layout 中的地图框中。
  2. 如果图层的投影到地图框的投影有多种转换方式,那么无法选择指定投影方式(尚未实现成功)
  3. 如果图层有子图层,无法选择子图层(ESRI Shapefile 中不会遇到)
  4. 如果图层需要访问验证,无法获取图层(ESRI Shapefile 中不会遇到)

在 QGIS 中,使用以下代码以较为完善地设置添加地图层,同时支持了很多其他功能。函数中创建的图层直接添加到 QgsProject 中,以支持 Layout 等功能。

QgsVectorLayer *QgsSdkApp::addVectorLayer(const QString &vectorLayerPath, const QString &name, const QString &providerKey, bool guiWarning)
{
    
    QString baseName = QgsMapLayer::formatLayerName( name );

    /* Eliminate the need to instantiate the layer based on provider type.
         The caller is responsible for cobbling together the needed information to
         open the layer
         */
    QgsDebugMsg( "Creating new vector layer using " + vectorLayerPath
                 + " with baseName of " + baseName
                 + " and providerKey of " + providerKey );

    // if th
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值