Qgis 开发低级 《数据库和图层》

打印 上一主题 下一主题

主题 982|帖子 982|积分 2946

Qgis 可以加载许多数据源,像shapefile 文件, gdb文件等,还可以直接链接企业数据库。在这里,我只先容比较常用的本地数据库 gdb。gdb 是esri 开发的数据库,gdb数据库不是开源的,qigs用了OpenFileGdb的驱动读写的,这个驱动目前是支持读写的。Qgis 读写数据库做了一层封装的,读写都是通过Qgis 的图层类实现,所以这里和图层一起先容。
1、数据库操纵

1.1、数据库的读取

读取数据库里面的某个表,从数据库的表到Qgis的QgsVectorLayer 矢量图层类中。参数表示 读取 D盘 test.gdb 的 名为 point 的表。注意这里 |layername= 附近 不要有空格,否则可能会读取失败。
  1. QString layerName="point";
  2. QString dbPath="D:\\test.gdb"+"|layername="+layerName;
  3. QgsVectorLayer* gdbLayer = new QgsVectorLayer(dbPath, layerName, QStringLiteral("ogr"));
复制代码
1.2、数据库的写入

这里会将QgsVectorLayer 写入到gdb中。
  1. QgsVectorFileWriter::SaveVectorOptions options;
  2. options.actionOnExistingFile = QgsVectorFileWriter::AppendToLayerNoNewFields;
  3. options.driverName = "openFileGDB";
  4. options.layerName = layerName;
  5. QgsCoordinateTransform ct;
  6. ct = QgsCoordinateTransform(vectorlayer->crs(), vectorlayer->crs(), vectorlayer->transformContext());
  7. ptions.ct = ct;
  8. QgsVectorFileWriter::writeAsVectorFormatV3(vectorlayer, cds.workSpacePath(), vectorlayer->transformContext(), options);
复制代码
此中QgsVectorFileWriter::AppendToLayerNoNewFields是个枚举值。 通过它来确定命据库记录是覆盖还是增加。
  enum ActionOnExistingFile
    {
      //! Create or overwrite file
      CreateOrOverwriteFile,
      //! Create or overwrite layer
      CreateOrOverwriteLayer,
      //! Append features to existing layer, but do not create new fields
      AppendToLayerNoNewFields,
      //! Append features to existing layer, and create new fields if needed
      AppendToLayerAddFields
    };

2、图层的操纵

Qgis的图层是Qgis封装的通用类,Qgis 用它屏蔽了数据源的差异,使用它可以操纵所有的数据源。数据库的字段和记录都是通过Qgis的图层来实现的。Qgis 里面有各种类型的图层,跟gdb 有关的重要是QgsVectorLayer的矢量图层。

2.1、 图层的新建和添加

        图层第一种创建方式就是从数据库读取的图层。这个时间图层是与数据库表同步的。获取方法参考 1.1 数据库的读取。
        图层第二种创建是直接创建内存图层, 创建一个名字叫 test的点图层,并设置坐标系。
  1. QgsVectorLayer* layer=new QgsVectorLayer("PointZ", "test", "memory");
  2. layer->setCrs(QgsProject::instance()->crs());
复制代码
这种创建的第一个参数是Qgis 的类型,该类型是个枚举,点,线,面都可以创建,枚举如下,创建的时间直接写字符串就可以。
  1. enum Type
  2.     {
  3.       Unknown = 0,
  4.       Point = 1,
  5.       LineString = 2,
  6.       Polygon = 3,
  7.       Triangle = 17,
  8.       MultiPoint = 4,
  9.       MultiLineString = 5,
  10.       MultiPolygon = 6,
  11.       GeometryCollection = 7,
  12.       CircularString = 8,
  13.       CompoundCurve = 9,
  14.       CurvePolygon = 10, //13, //should be 10. Seems to be correct in newer PostGIS versions
  15.       MultiCurve = 11,
  16.       MultiSurface = 12,
  17.       NoGeometry = 100, //attributes only
  18.       PointZ = 1001,
  19.       LineStringZ = 1002,
  20.       PolygonZ = 1003,
  21.       TriangleZ = 1017,
  22.       MultiPointZ = 1004,
  23.       MultiLineStringZ = 1005,
  24.       MultiPolygonZ = 1006,
  25.       GeometryCollectionZ = 1007,
  26.       CircularStringZ = 1008,
  27.       CompoundCurveZ = 1009,
  28.       CurvePolygonZ = 1010,
  29.       MultiCurveZ = 1011,
  30.       MultiSurfaceZ = 1012,
  31.       PointM = 2001,
  32.       LineStringM = 2002,
  33.       PolygonM = 2003,
  34.       TriangleM = 2017,
  35.       MultiPointM = 2004,
  36.       MultiLineStringM = 2005,
  37.       MultiPolygonM = 2006,
  38.       GeometryCollectionM = 2007,
  39.       CircularStringM = 2008,
  40.       CompoundCurveM = 2009,
  41.       CurvePolygonM = 2010,
  42.       MultiCurveM = 2011,
  43.       MultiSurfaceM = 2012,
  44.       PointZM = 3001,
  45.       LineStringZM = 3002,
  46.       PolygonZM = 3003,
  47.       MultiPointZM = 3004,
  48.       MultiLineStringZM = 3005,
  49.       MultiPolygonZM = 3006,
  50.       GeometryCollectionZM = 3007,
  51.       CircularStringZM = 3008,
  52.       CompoundCurveZM = 3009,
  53.       CurvePolygonZM = 3010,
  54.       MultiCurveZM = 3011,
  55.       MultiSurfaceZM = 3012,
  56.       TriangleZM = 3017,
  57.       Point25D = 0x80000001,
  58.       LineString25D,
  59.       Polygon25D,
  60.       MultiPoint25D,
  61.       MultiLineString25D,
  62.       MultiPolygon25D
  63.     };
复制代码
这种方式再先容下指定地方坐标系的情况,str 填写的是坐标系的 wkt 字符串。此中layer 是QgsVectorLayer * 的指针对象。
  1. QString str = "";
  2. QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromWkt(str);
  3. layer->setCrs(crs);
复制代码
这两种图层创建后,其实还没到场到Qgis 工程中。通过QgsProject 到场到工程中。代码如下。
  1. QgsProject::instance()->addMapLayer(layer);
复制代码
到场到工程中的图层,可以通过名字大概ID 重新获取指针。下面代码是获取名字叫test的图层。mapLayersByName 返回的是QList 列表对象。因为Qgis 多个图层可以叫同一个名字。当然可以通过layer的id获取,再次不多先容了。
  1. QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>(QgsProject::instance()->mapLayersByName("test").at(0));
复制代码
2.2、 图层的删除

此中di 是 图层QgsVectorLayer * 的指针对象 的图层id; 这个里面会自动删除指针对象。
  1. QgsProject::instance()->removeMapLayer(id);
复制代码

2.3、图层的显隐

这里需要先容下图层显隐控制,图层的显隐控制不是在图层级别的,是与图层的控件有关系的。好比根据某个图层id来隐蔽图层。
  1. QgsLayerTreeView* layerTreeView = interface->layerTreeView();
  2. QgsLayerTreeLayer* nodeLayer = layerTreeView ->layerTreeModel()->rootGroup()->findLayer(layer->id());
  3. nodeLayer->setItemVisibilityChecked(false);
复制代码
2.4、图层的重绘

这是一个很重要的操纵,可以单独刷新某个图层,有些操纵如果不调用这个方法时看不到新增要素的。
  1. layer->triggerRepaint()
复制代码

2.5、添加字段

Qgis 添加字段涉及到 QgsField 的类,如下代码,添加了一个String 类型的 Name 字段,一个Double类型的X 字段和一个Double类型的Y字段。Qgis 是用Qt 开发,经常会用到一些qt的语法。此中layer 是QgsVectorLayer * 的指针对象。
  1. QList<QgsField> fieldList;
  2. fieldList.append(QgsField("Name", QVariant::String));
  3. fieldList.append(QgsField("X", QVariant::Double));
  4. fieldList.append(QgsField("Y", QVariant::Double));
  5. QgsVectorDataProvider* provider=layer->dataProvider();
  6. provider->addAttributes(fieldList);
  7. layer->updateFields();
复制代码
3 、要素操纵

图层和字段创建好了后,就需要对要素做进一步操纵。重要实现增删改查,图层的要素编辑其实有两种,一种在编辑模式下,一种不在编辑模式下。两种的区别是编辑模式思量的用户操纵体验,可以做回撤,重做等操纵,批处理惩罚时,服从相对较低。非编辑模式下直接操纵同步数据库,服从比较高。这里先先容下非编辑模式。Qgis的要素类是QgsFeature。 代表着数据库中的一行记录。
3.1 、添加要素

添加要素的代码如下,首先,创建QgsFature对象,此中layer 是QgsVectorLayer * 的指针对象。
  1. QgsFeature feature = QgsFeature(layer->fields());
  2. QgsVectorDataProvider* provider = layer->dataProvider();
  3. provider->addFeature(feature );
复制代码
也可以用addFeatures 批量添加,这种方式应该更快一些。QList 可以换成QgsFeatureList 是一样,QgsFeatureList 是QList<QgsFeature> 的宏下令。
  1. QList<QgsFeature> features;
  2. QgsFeature feature = QgsFeature(layer->fields());
  3. features.push_back(feature );
  4. QgsVectorDataProvider* provider = layer->dataProvider();
  5. provider->addFeatures(features);
复制代码

添加多少字段值,在平面坐标系下这样操纵。在setGeometry 的参数是QgsGeometry。这个对象的详细操纵会在后面先容。注意,添加的多少,要与创建的图层一致,图层是点,添加点,图层是线,添加线,
  1. feature.setGeometry(QgsGeometry::fromPointXY(QgsPointXY(1000, 1000)));
复制代码
添加字段属性值,单个添加。
  1. feature.setAttribute("X", 1000);
  2. feature.setAttribute("Y", 1000);
复制代码
也可以批量添加属性。但是要注意属性的顺序。
  1. feature.setAttributes(QgsAttributes() << "Point 1");
复制代码
3.2、要素更新

要素更新,重要更新地理字段和属性字段。可以使用下面的方法批量添加地理字段和属性字段。此中index 是字段的所在字段索引,id 是QgsFeature的 id ,layer  是 QgsVectorLayer * 的指针对象。 类型是QgsFeatureId。此中geo 和 amap 的不在举例子了。
  1.         QgsGeometry geo;
  2.     QgsAttributeMap amap;
  3.     amap.insert(index, 1000);
  4.     QgsChangedAttributesMap camap;
  5.         QgsGeometryMap geoMap;
  6.     camap.insert(id,amap);
  7.     geoMap.insert(id,geo);
  8.         layer->dataProvider()->changeFeatures(camap, geoMap);
复制代码

3.3、要素删除

        通过以下方法删除要素
  1. QgsFeatureIds ids;
  2. layer->dataProvider()->deleteFeatures(ids);
复制代码
4、编辑模式

编辑模式需要单独拿出来说一下,要素的增删改查可以在编辑模式下执行,在非编辑模式下做增删改查更快,更在乎的是服从,编辑模式相对慢一些,因为它需要更多的流程,整个编辑过程是可以追溯的,可撤销,可规复,编辑模式一般是交互式的增删改查,更在乎的是用户体验。此中设计到layer 都以为是QgsVectorLayer 的对象指针。
4.1、开启和停止

一般来说,编辑模式都是针对的矢量图层。
  1. layer->startEditing();
复制代码
停止编辑并保存要素是一个操纵,如果想保存继续编辑,还需要调用一次开启编辑。
  1. layer->commitChanges();
复制代码
判断是否开启编辑
  1. layer->isEditable()
复制代码
4.2、事务

下面的两个下令也是非常重要,在编辑模式下非常重要的就是回退,在beginEditCommand和endEditCommand的任何增删改查操纵在图层回退大概重做时会被以为一次操纵。
  1. layer->beginEditCommand("当前图层");
  2. layer->endEditCommand();
复制代码

4.3、增加要素

要素增加,和非编辑下就一行代码不一样,实在图层级别直接添加。如下
  1. layer->addFeature(feature)
复制代码
4.4、要素更新

修改要素,此中id是QgsFeatureId。
  1. QgsGeometry geo;
  2. QgsAttributeMap amap;
  3. layer->changeGeometry(id, geo);
  4. layer->changeAttributeValues(id, amap);
复制代码
4.5、要素删除

此中id是QgsFeatureId。
  1. layer->deleteFeature(id)
复制代码
4.6、要素的回退和重做

回退
  1. auto undostack = layer->undoStack();
  2. undostack->redo();
复制代码
重做
  1. auto undostack = layer->undoStack();
  2. undostack->undo();
复制代码

5、小节

        我们先容了数据库的操纵,图层和要素的操纵,此中图层和要素在非编辑模式下的操纵,也是比较高服从的操纵。编辑模式下的操纵其实类似,编辑模式其实是与后面的交互一起使用,只有这样才气实现通过交互来增加要素,后面会先容qgis的交互变乱。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万有斥力

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表