矢量图层属性的图表显示功能,帮助我们以图形化的方式更直观地显示数据当中的信息,使得数据生动起来的同时也变得更美观。QGis当中提供了默认三种图表,分别是饼状图、柱状图以及文本图。下面我们就来看一下在二次开发中如何实现这样的功能。
饼状图
![这里写图片描述](https://img-blog.csdn.net/20160411225842989)
文本图
![这里写图片描述](https://img-blog.csdn.net/20160411225905849)
柱状图
![这里写图片描述](https://img-blog.csdn.net/20160411225925802)
QgsDiagramRendererV2
首先,认识一下控制图表显示的渲染类 QgsDiagramRendererV2。这个类在 QgsVectorLayer 中具有引用指针,通过 QgsVectorLayer 的 setDiagramRenderer() 方法,传入一个 QgsDiagramRendererV2 的实例,当前的矢量图层就会以设置的方法来渲染显示图表。但是 QgsDiagramRendererV2 是一个抽象类,并不能直接实现它的实例,而应该进一步选择实现它的子类。继承关系如下图:
![这里写图片描述](https://img-blog.csdn.net/20160411201847332)
其中 QgsLinearlyInterpolatedDiagramRenderer 和 QgsSingleCategoryDiagramRenderer 分别是具体的渲染方法类,具体算法的不同请参阅API文档,这里仅讨论快速让图表显示出来,至于显示的方式,还需要同学们根据需求自己进行设置。
有了渲染类,到底是以饼状图、文本图还是柱状图的方式来显示,还需要通过渲染类的 setDiagram() 方法来设置。下面就来看看具体的图表类。
Diagram类
QGis当中提供的图表类包括三个,QgsPieDiagram、QgsTextDiagram 和 QgsHistogramDiagram,它们分别对应于饼状图、文本图和柱状图,都是继承自 QgsDiagram 类,继承关系如下图:
![这里写图片描述](https://img-blog.csdn.net/20160411202922383)
图表类并不需要额外的参数,仅初始化就可以了。当然,它们具有一系列的参数可供配置。如果将每个类的参数都封装在类里面,不仅重复代码会增多,而且并不便于管理,况且不论是哪一种图表,它们都具有某些共通的设置参数。于是QGis把这些参数通过其他类进行统一管理。具体来说,有两个,一个是QgsDiagramSettings,用于配置针对图表的参数,另一个是 QgsDiagramLayerSettings,是更高一级的参数,将图表类作为一个图层,配置与矢量要素的显示关系。
QgsDiagramSettings
专门用于图表配置属性的类,这个类的定义是包含在 qgsdiagramrendererV2.h 这个文件中的,由于上文用到了 QgsDiagramRendererV2,想必你应该已经添加了这个头文件的 include 了。
QgsDiagramSettings 类包含的图表属性包括字体、大小、颜色等等,下图来源于 API 文档,可以比较详细的看到可配置的属性:
![这里写图片描述](https://img-blog.csdn.net/20160411204129856)
为了方便大家理解上面的这些属性,列表如下,利用这些参数设置,基本就能够满足图表的不同显示方式了。
Name | 说明 |
---|
angleOffset | 起始角度(仅饼状图) |
backgroundColor | 背景颜色 |
barWidth | 柱宽度(仅柱状图) |
categoryAttributes \ categoryColors | 用于控制不同属性显示不同颜色 |
diagramOrientation | 图表方向 |
font | 字体(仅文本图) |
labelPlacementMethod | 图表中文本的显示位置(仅文本图),包括Hight和XHight |
maxScaleDenominator \ minScaleDenominator | 显示尺度。大于或小于缩放尺度,图表将不再显示 |
minimumSize | 图表显示的最小尺寸。小于这个尺寸的图表会放大到这个尺寸显示 |
penColor \ penWidth | 控制轮廓的颜色和宽度 |
scaleByArea | 是否根据要素面积进行缩放图表(仅polygon要素) |
size | 图表大小 |
sizeType | 图表大小的单位,包括 MM 和 MapUnits |
transparency | 透明度 |
QgsDiagramLayerSettings
这个类控制图表作为一个图层,具有的显示方式,包括距离要素的长度、显示相对于要素的方式等。同样,从API文档中查看它具有的属性。
![这里写图片描述](https://img-blog.csdn.net/20160411212335316)
还是列表进行说明:
Name | 说明 |
---|
ct | QgsCoordinateTransform类型常量指针 |
dist | 与要素相隔的距离 |
fields | 指定用于显示图表的要素字段 |
geometries | QgsPalGeometry类型列表,指示当前要素类型 |
obstacle | 是否阻挡要素显示 |
palLayer | 当前图层指针 |
placement | 显示位置,包括AroundPoint\OverPoint\Line\Curved\Horizontal\Free |
placementFlags | 现状要素的显示位置,包括 OnLine\AboveLine\BelowLine\MapOrientation |
priority | 显示优先级 |
renderer | 指定QgsDiagramRendererV2类型的指针 |
xform | QgsMapToPixel类常量 |
xPosColumn \ yPosColumn | 由数据定义图表位置 |
调用方式
通过上文的分析,要实现图表功能就比较清晰了。
首先,要有一个 QgsVectorLayer,指向当前的矢量图层
// 这一句是获取当前图层,修改成你自己获取当前图层的方式
QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( activeLayer() );
然后,需要一个具体的 Diagram,这里以柱状图为例
QgsDiagram* diagram = new QgsHistogramDiagram();
接着,定义 QgsDiagramSettings类,并设置它的参数
QgsDiagramSettings ds; // diagram的设置项
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" )
{
}
else if ( diagramType == "Pie" )
{
}
else
{
diagram = new QgsHistogramDiagram();
}
#pragma region 设置diagram属性
QgsDiagramSettings ds;
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;
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();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
若文中有错误,请不吝指正,谢谢!