QGis⼆次开发基础--⽂字标注
Label 这个功能是为了更直观的将⽮量数据的属性信息显⽰在地图上,⽅便⽤户在浏览地图的时候查看。⼏乎每个 Gis 系统都会有这个基础功能,QGis 的 Label 更是⾮常漂亮,不仅⽀持标注的轮廓缓冲区功能,还可以给标注绘制上阴影效果等。今天就来说⼀说 QGis ⼆次开发中的⽂字标注功能的实现。
在这⾥补充⼀点:如果你的 QGis 显⽰出的⽮量图层中⽂是乱码,不论是属性表⾥⾯的乱码还是 Label 上显⽰的乱码,都是字符编码的问题。
照下⾯的图,在图层属性⾥⾯,打开“通⽤”⾯板,设置“数据源编码”为“GBK”或者“GBK2312”就可以了。
本⽂包含两个部分,第⼀是直接实现 Label 功能,第⼆则是教⼤家直接把 QGis 的 Label 配置⾯板拿过来⽤。
实现思路
⾸先我们注意到,QgsVectorLayer 这个类当中,有⼀个 enableLabels() ⽅法。先好奇的将它设置为 true.
QgsVectorLayer* layer = (QgsVectorlayer*)this->activeLayer(); // 替换成任何⼀种获取⽮量图层的⽅式
layer->enableLabels(true);
m_mapCanvas->refresh();
发现有如下的效果:
OK,Done!谢谢阅读。
哈哈,开个玩笑。
上图所⽰的结果,仅仅是打开了 Label 这个功能,它⾮常简单,但是到现在还没有任何配置。例如,我们要显⽰的字段,显⽰出来的样⼦等等。
可是我们确实已经实现了标注的功能,即在地图界⾯中显⽰出了⽂字信息。
于是我们发现,重点应该是如何配置这个标注的显⽰。
如果某个对象有⼀⼤堆属性需要设置,最好的⽅式就是新建另⼀个对象,来负责设置这些属性。 这个类正是这样的存在,它负责⽮量图层的相关设置。看⼀看 API ⽂档,不难发现,这⾥⾯定义的⼏乎全都是属性。
我相信配置属性对于⼤家来说都不会是⼀个难点,⽆⾮就是给不同的属性赋上不同的值⽽已。下⾯我会通过代码注释,来直接给出使⽤⽅法。
// ⾸先是定义⼀个 QgsPalLayerSettings 变量,并启⽤他的属性设置
QgsPalLayerSettings layerSettings;
// 然后就可以开始根据API⽂档中的属性,进⾏⾃定义配置了
layerSettings.fieldName = layer->pendingFields()[3].name(); // 设置Label图层
// Label 字体设置
// Label 轮廓buffer设置
layerSettings.bufferDraw = true;
layerSettings.bufferColor = QColor( 255, 0, 0 ); // 轮廓buffer的颜⾊
layerSettings.bufferSize = 1; // 轮廓buffer⼤⼩
layerSettings.bufferTransp = 0.5; // 轮廓buffer的透明度
// Label 阴影绘制
layerSettings.shadowDraw = true;
layerSettings.shadowOffsetAngle = 135; // 阴影的⾓度
layerSettings.shadowOffsetDist = 1; // 阴影与Label的距离
QgsVectorLayer* layer = (QgsVectorlayer*)this->activeLayer(); // 替换成任何⼀种获取⽮量图层的⽅式
layerSettings.writeToLayer( layer ); // 将配置写⼊图层
m_mapCanvas->refresh();
注意,最后⼀定要⽤ writeToLayer() ⽅法把设置写到相应的图层中。上⾯的代码效果如下图:
⾄于想要更特别的显⽰效果,就⾃⼰去相应的属性进⾏设置就可以了。
数据定义的标注样式
这⾥再多说⼀点,QgsPalLayerSettings 的定义中,第⼀个变量就是叫 的枚举类型,这个枚举类型⾥
⾯定义的属性,其实在QgsPalLayerSettings 的公共属性中是对应的,那么它的作⽤是什么呢?其实,正如它的名字那样,DataDefinedProperties 是由数据定义的属性,也就说,同⼀个图层的属性可以是动态变化的。⽐如说同⼀个图层中,有两个 Feature,想要将这两个 Feature 的 Label 显⽰为不同⼤⼩,甚⾄不同的颜⾊、字体等。就可以定义⼀个 size 的字段来存储⼤⼩,color 的字段存储颜⾊, font 字段存储字体。这样,这两个 Feature 显⽰出来的 Label 样式就会不⼀样,并且是跟随数据的改变⽽改变的。
还是通过实际操作来解释会更直观⼀点。
现在我们新增加 3 个字段到测试图层中。注意我们新增的 color 表⽰为⼗六进制的颜⾊字符串,并且为了显⽰⽅便,在这个测试图层中,我们仅保留了 3 个要素。
我们在 QGis 的 Label 属性⾯板中,做如下的设置
点击确定,就可以得到如下图所⽰的效果,即这 3 个要素显⽰的 Label 样式各不相同。
那么,怎么通过代码来实现这个功能呢?我们注意到,QgsPalLayerSettings 类中,包含了⼀个 ⽅法,定义如下:
使⽤这个⽅法,我们就可以达到以上 QGis 中实现的 Label 不同样式的功能了。测试代码如下:
// 同样定义⼀个 QgsPalLayerSettings 变量,并启⽤他的属性设置
QgsPalLayerSettings layerSettings;
// 设置显⽰字段
layerSettings.fieldName = layer->pendingFields()[3].name();
layerSettings.setDataDefinedProperty( layerSettings.Size, true, false, NULL, "size" ); // 设置 Label ⼤⼩
layerSettings.setDataDefinedProperty( layerSettings.Color, true, false, NULL, "color" ); // 设置 Label 颜⾊
layerSettings.setDataDefinedProperty( layerSettings.Family, true, false, NULL, "font" ); // 设置 Label 字体
QgsVectorLayer* layer = (QgsVectorlayer*)this->activeLayer(); // 替换成任何⼀种获取⽮量图层的⽅式
layerSettings.writeToLayer( layer ); // 将配置写⼊图层
m_mapCanvas->refresh();
运⾏这段代码会得到与上⾯ QGis 中显⽰相同的效果。
复制 QGis 标注配置⾯板
配置代码主要都是重复性劳动,还要做 UI 显⽰,⽐较复杂。如果你对 UI 没有特别的要求,⾃然就想到直接⽤ QGis 的配置⾯板吧。这个也⽐较 easy,也就是复制源码中相关的⽂件到⾃⼰的⼯程,然后调⽤就可以了。这⼏个⽂件分别是:
qgslabelpreview.h 以及 qgslabelpreview.cpp
qgslabelinggui.h 以及 qgslabelinggui.cpp
qgsmapunitscaledialog.ui
widget_svgselector.ui
qgsunitselectionwidget.ui
qgsmapunitscaledialog.ui
qgslabelingguibase.ui
qgsexpressionbuilder.ui
qgscharacterselectdialogbase.ui
(希望我没有漏掉⽂件)box shadow怎么设置
其中, qgslabelinggui 类就是我们可以直接调⽤的窗⼝,它的 UI ⽂件为 qgslabelingguibase.ui 。我们只需要新建⼀个 QDialog 窗⼝,并新建⼀个 qgslabelinggui 类放⼊这个窗⼝,然后调⽤它的 init ⽅法和 QDialog 的 show ⽅法就可以了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论