QGIS二次开发--矢量图层属性图标表示

博客介绍了矢量图层属性的图标显示功能,重点讲解了QgsDiagamRenderV2。它是控制图表的渲染类,但为抽象类,需选择子类实现。还介绍了QGis提供的图标类,以及用于管理参数的QgsDiagramSettings和QgsDiagramLayerSettings类,最后给出调用方式和示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

矢量图层属性的图标显示功能,能够帮助我们以图形化的方式直观地显示数据中的信息,使得数据生动起来的同时也变得美观起来。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

QgsDiagamRenderV2

首先认识一下控制图表的渲染类,QgsDiagramRenderV2。该类在QgsVectorLayer具有引用指针,通过 QgsVectorLayer 的 setDiagramRenderer() 方法,传入一个 QgsDiagramRendererV2 的实例,当前的矢量图层就会以设置的方法来渲染显示图表。但是 QgsDiagramRendererV2 是一个抽象类,并不能直接实现它的实例,而应该进一步选择实现它的子类。
在这里插入图片描述
其中 QgsLinearlyInterpolatedDiagramRenderer 和 QgsSingleCategoryDiagramRenderer 是具体的渲染方法类,具体算法的不同请参阅API文档。
有了渲染类到底是以饼状图还是以文本或柱状图来显示,还需要通过渲染类的setDiagram() 方法来设置。下面就来看看具体的图表类。

Diagram类
QGis中提供的图标类包括三个:QgsPieDiagram、QgsTextDiagram和QgsHistogramDiagram。它们分别对应于饼状图、文本图和柱状图,均继承于QgsDiagram类。
继承关系如下图所示:
在这里插入图片描述
图表类并不需要额外的参数,仅初始化就可以了。当然,它们具有一系列的参数可供配置。如果将每个类的参数都封装在类里面,不仅重复代码会增多,而且并不便于管理,况且不论是哪一种图表,它们都具有某些共通的设置参数。于是QGis把这些参数通过其他类进行统一管理。具体来说,有两个,一个是QgsDiagramSettings,用于配置针对图表的参数,另一个是 QgsDiagramLayerSettings,是更高一级的参数,将图表类作为一个图层,配置与矢量要素的显示关系。

QgsDiagramSettings
专门用于图表配置属性的类,这个类的定义是包含在 qgsdiagramrendererV2.h 这个文件中的,由于上文用到了 QgsDiagramRendererV2,想必你应该已经添加了这个头文件的 include 了。

QgsDiagramSettings 类包含的图表属性包括字体、大小、颜色等等,下图来源于 API 文档,可以比较详细的看到可配置的属性:
在这里插入图片描述

在这里插入图片描述

QgsDiagramLayerSettings
这个类控制图标作为一个图层,具有的显示方式,包括要素的显示长度,显示相对对于要素的方式等。同样,从API文档中查看它具有的属性。
在这里插入图片描述
在这里插入图片描述
调用方式

首先,要有一个QgsVectorLayer,指向当前的矢量图层。

//这句话是获取当前图层,修改成你自己获取当前图层的方式
QgsVectorLayer * layer = qobject_cast<QgsVectorLayer*>(activeLayer());

然后需要一个具体的Diagram
这里以柱状图为例:

QgsDiagram * diagram = new QgsHistogramDiagram();

接着定义QgsDiagramSettings类,并设置它的参数

QgsDiagramSettings ds;
ds.transparency = 0;  //设置透明度
....
....

同样,定义 QgsDiagramLayerSettings类,并设置参数

QgsDiagramLayerSettings dls;
dls.dist = 0;  //与要素相隔的距离
dls.priority = 5; //设置优先级
....

还需要选择渲染类,并设置一些它的属性,这里以 QgsLinearlyInterpolatedDiagramRenderer 类为例。

QgsLinearlyInterpolatedDiagramRenderer*  dr = new QgsLinearlyInterpolatedDiagramRenderer();
dr->setLowerValue(0.0);

最后层层调用,并刷新一下显示。

dr->setDiagram(diagram);
dr->setDiagramSettings(ds);
layer->setDiagramRenderer( dr );
layer->setDiagramLayerSettings( dls );
layer->triggerRepaint();
mapCanvas->refresh();

示例代码,仅供大家参考。

void qgis_dev_layerPropDialog::setDiagramProperty()
{
    // 这一句是获取当前图层,修改成你自己获取当前图层的方式
    QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( activeLayer() ); 
 
    QgsDiagram* diagram = 0;
    QString diagramType = "Hist"; // 这一句修改成获取图表类型的代码
    bool scaleAttributeValueOk = false;
 
    QgsVectorDataProvider* provider = layer->dataProvider();
    double maxVal = 0;
    int fld = 2;
    if ( fld != -1 )
    {
        bool ok = false;
        double val = provider->maximumValue( fld ).toDouble( &ok ); // 获取该字段的最大值
        if ( ok )
        {
            maxVal = val;
        }
    }
    bool mValueLineEdit = false;
 
    if ( diagramType == "Text" )
    {
        //diagram = new QgsTextDiagram();
    }
    else if ( diagramType == "Pie" )
    {
        //diagram = new QgsPieDiagram();
    }
    else // if ( diagramType == DIAGRAM_NAME_HISTOGRAM )
    {
        diagram = new QgsHistogramDiagram();
    }
 
    #pragma region 设置diagram属性
 
    QgsDiagramSettings ds; // diagram的设置项
    //ds.font = mDiagramFont; // 设置字体
    ds.transparency = 0; // 设置透明度
 
    QList<QColor> categoryColors; // 颜色
    QList<QString> categoryAttributes; // 属性
 
    QColor color = QColor( 255, 0, 0 );
    color.setAlpha( 255 - ds.transparency );
    categoryColors.append( color );
    categoryAttributes.append( "ELEV" );
 
    ds.categoryColors = categoryColors;
    ds.categoryAttributes = categoryAttributes;
    ds.size = QSizeF( 1, 1 );
    ds.sizeType = static_cast<QgsDiagramSettings::SizeType>( 0 );
    ds.labelPlacementMethod = static_cast<QgsDiagramSettings::LabelPlacementMethod>( 1 );
    ds.scaleByArea = true;
 
 
    ds.minimumSize = 0;
 
    ds.backgroundColor = QColor( 0, 0, 0 ); // 背景色
    ds.penColor = QColor( 0, 0, 0 ); // 轮廓颜色
    ds.penWidth = 1; // 轮廓宽度
 
    ds.minScaleDenominator = -1;
    ds.maxScaleDenominator = -1;
 
    // Diagram 方向 (histogram)
    ds.angleOffset = 1440;
    ds.diagramOrientation = static_cast<QgsDiagramSettings::DiagramOrientation>( 0 );
 
    ds.barWidth = 5; // 宽度
    #pragma endregion 设置diagram属性
 
    QgsLinearlyInterpolatedDiagramRenderer* dr = new QgsLinearlyInterpolatedDiagramRenderer();
    dr->setLowerValue( 0.0 );
    dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
    dr->setUpperValue( 2 );
    dr->setUpperSize( QSizeF( 2, 2 ) );
 
    bool isExpression = true;
    dr->setClassificationAttributeIsExpression( isExpression );
 
    dr->setClassificationAttributeExpression( "" );
 
    dr->setDiagram( diagram );
    dr->setDiagramSettings( ds );
    layer->setDiagramRenderer( dr );
 
    QgsDiagramLayerSettings dls;
    dls.dist = 0;
    dls.priority = 5;
 
    dls.xPosColumn = -1;
    dls.yPosColumn = -1;
    dls.placement = static_cast<QgsDiagramLayerSettings::Placement>( 0 );
 
    dls.placementFlags = 0;
    layer->setDiagramLayerSettings( dls );
 
    layer->setTitle( "" );
 
    QgsVectorSimplifyMethod simplifyMethod = m_layer->simplifyMethod();
    simplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
    simplifyMethod.setThreshold( 1 );
    simplifyMethod.setForceLocalOptimization( true );
    simplifyMethod.setMaximumScale( 1 );
    layer->setSimplifyMethod( simplifyMethod );
 
    layer->triggerRepaint();
    m_mapCanvas->refresh(); // 改成你自己的 map canvas
}

转自https://blog.youkuaiyun.com/shineplusplus/article/details/78362098

<think>我们正在解决QGIS二次开发中给矢量图层添加属性的问题。用户可能使用Python或C++API,由于上一个问题中提到了PythonMapScript,但用户明确询问QGIS二次开发,因此我们将聚焦QGIS的API。根据QGIS的API文档,给矢量图层添加属性通常需要以下步骤:1.确保图层处于编辑模式(startEditing)2.使用数据提供者(dataProvider)添加属性字段(addAttributes)3.提交更改(commitChanges)或回滚(rollback)在Python中,可以使用以下代码示例:```python#假设有一个矢量图层layerlayer=iface.activeLayer()#获取当前活动图层#1.开始编辑layer.startEditing()#2.添加属性字段,需要创建一个QgsField对象#参数:字段名(字符串),字段类型(QVariant.Type)fromqgis.coreimportQgsFieldnew_field=QgsField('new_field_name',QVariant.String)#这里创建了一个字符串类型的字段#获取数据提供者provider=layer.dataProvider()#使用addAttributes方法添加字段,参数是一个列表res=provider.addAttributes([new_field])#3.提交更改layer.commitChanges()#或者回滚:layer.rollback()#注意:addAttributes返回一个布尔值,表示是否成功```在C++中,步骤类似:```cpp//假设有一个QgsVectorLayer指针layerlayer->startEditing();//创建字段QgsFieldnewField("new_field_name",QVariant::String);//获取数据提供者QgsVectorDataProvider*provider=layer->dataProvider();//添加字段boolres=provider->addAttributes(QList<QgsField>()<< newField);//提交更改layer->commitChanges();```注意:在QGIS中,字段类型使用QVariant类型系统,常见的类型有:-QVariant.String(字符串)-QVariant.Int(整数)-QVariant.Double(浮点数)-QVariant.Date(日期)另外,在添加字段之前,需要确保图层是矢量图层(如点、线、面),并且支持编辑。如果是在插件开发中,可能需要考虑用户界面刷新,在提交更改后,可能需要触发图层的重绘或属性表的更新。常见问题:1.未进入编辑模式就添加字段会导致失败。2.添加字段后忘记提交更改,则更改不会保存。3.添加的字段名已存在会导致失败。因此,在实际代码中,建议检查每一步的返回值。参考QGIS官方文档[^1]和[^2]获取更多细节。生成相关问题:§§相关问题§§1.如何检查QGIS图层是否支持编辑?2.如何在QGIS中创建自定义矢量图层?3.如何删除矢量图层中的属性字段?4.如何批量添加多个属性字段?注意:由于我们是在QGIS环境下开发,所以上述代码需要运行在QGISPython控制台或插件中,或者使用PyQGIS独立脚本(需要配置环境)。在C++开发中,通常是在QGIS桌面应用程序的插件或自定义应用程序中使用。</think> ### 📚 QGIS矢量图层添加属性字段详解 在QGIS二次开发中,给矢量图层添加属性字段主要有以下两种方式,下面分别从Python和C++ API角度详细说明: #### 🔧 Python API (PyQGIS) 实现 ```python # 获取当前活动图层(也可通过路径加载图层) layer = iface.activeLayer() # 开始编辑会话 layer.startEditing() # 创建新字段对象 from qgis.core import QgsField new_field = QgsField( "population", # 字段名 QVariant.Int, # 字段类型(整型) "integer", # 字段类型字符串 len=10 # 字段长度(可选) ) # 向数据提供者添加字段 data_provider = layer.dataProvider() if data_provider.addAttributes([new_field]): # 更新字段列表并提交更改 layer.updateFields() layer.commitChanges() print("成功添加字段!") else: print("添加字段失败") ``` 常用字段类型常量: - `QVariant.Int`:整型 - `QVariant.Double`:浮点型 - `QVariant.String`:字符串 - `QVariant.Date`:日期型 #### ⚙ C++ API 实现 ```cpp // 获取矢量图层 QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>(activeLayer()); // 开始编辑 layer->startEditing(); // 创建字段定义 QgsField newField("population", QVariant::Int, "integer"); // 获取数据提供者 QgsVectorDataProvider* provider = layer->dataProvider(); // 添加字段 QList<QgsField> fields; fields.append(newField); if (provider->addAttributes(fields)) { // 更新字段并提交 layer->updateFields(); layer->commitChanges(); qDebug() << "字段添加成功!"; } else { qDebug() << "添加字段失败"; } ``` #### 💡 关键注意事项 1. **编辑模式**:必须先进入编辑模式`startEditing()`才能修改字段结构 2. **数据提供者**:字段操作必须通过图层的`dataProvider()`对象完成 3. **字段定义**:确保字段类型与数据兼容: - 整数类型用`QgsField::Int`或`QVariant::Int` - 浮点型用`QgsField::Double`或`QVariant::Double` 4. **批量添加**:可一次性添加多个字段(将多个字段对象放入列表/QList) 5. **数据持久化**:添加后必须调用`commitChanges()`才能永久保存修改 > **重要提示**:当操作外部格式数据集(如Shapefile)时,添加字段可能导致整个数据复制[^2],建议操作前备份数据。 #### 🧪 常见错误处理 ```python # 检查图层类型(确保是矢量图层) if not isinstance(layer, QgsVectorLayer): raise TypeError("仅支持矢量图层") # 检查字段名是否已存在 if layer.fields().indexOf("population") != -1: print("字段名已存在!") ``` #### 🔍 相关文档参考 - QgsVectorLayer类文档:https://qgis.org/pyqgis/3.22/core/QgsVectorLayer.html - 字段类型完整列表:https://qgis.org/api/classQgsField.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值