跳转至

3 加载图层⚓︎

此页面上的代码片段需要导入以下模块:

1
2
3
4
import os # pyqgis控制台同样需要
from qgis.core import (
    QgsVectorLayer
)

让我们使用数据打开一些图层。QGIS可识别矢量和栅格图层。此外,自定义图层类型也可以使用,但我们不打算在此讨论。

3.1 矢量图层⚓︎

创建一个矢量图层实例,指定图层的数据源标识、图层名称和提供者名称:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 获取shapefile的路径,例如:/home/project/data/ports.shp 
path_to_airports_layer = "testdata/airports.shp"

# 格式为:
# vlayer = QgsVectorLayer(data_source, layer_name, provider_name)

vlayer = QgsVectorLayer(path_to_ports_layer, "Airports layer", "ogr")

if not vlayer.isValid():
    print("图层加载失败!")
else:
    QgsProject.instance().addMapLayer(vlayer)

数据源标识是一个字符串,它特定于每个矢量数据提供者。图层名称用于图层列表部件。检查图层是否已成功加载非常重要。如果不是,则返回无效的图层实例。

geopackage矢量图层:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 获取geopackage的路径,例如:/home/project/data/data.gpkg 
path_to_gpkg = os.path.join(QgsProject.instance().homePath(), "data", "data.gpkg")
# 追加图层名称
gpkg_places_layer = path_to_gpkg + "|layername=places"
# 例如:gpkg_places_layer = "/home/project/data/data.gpkg|layername=places"
vlayer = QgsVectorLayer(gpkg_places_layer, "Places layer", "ogr")
if not vlayer.isValid():
    print("图层加载失败!")
else:
    QgsProject.instance().addMapLayer(vlayer)

在QGIS中打开并显示矢量图层的最快方式是使用QgisInterface类的 addVectorLayer() 方法:

1
2
3
vlayer = iface.addVectorLayer(path_to_ports_layer, "Ports layer", "ogr")
if not vlayer:
    print("图层加载失败!")

这将创建一个新图层,并将其添加到当前QGIS项目中(使其显示在图层列表中)。该函数返回图层实例,如果无法加载图层则返回None

以下列表展示了如何使用矢量数据提供者访问各种数据源:

  • GDAL 库(Shapefile和许多其他文件格式)——数据源是文件的路径:

  • Shapefile:

    1
    2
    vlayer = QgsVectorLayer("/path/to/shapefile/file.shp", "layer_name_you_like", "ogr")
    QgsProject.instance().addMapLayer(vlayer)
    
  • dxf(注意数据源uri中的内部选项):

    1
    2
    3
    uri = "/path/to/dxffile/file.dxf|layername=entities|geometrytype=Point"
    vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
    QgsProject.instance().addMapLayer(vlayer)
    
  • PostGIS 数据库——数据源是一个字符串,其中包含与PostgreSQL数据库创建连接所需的所有信息。

    QgsDataSourceUri类可以为你生成这个字符串。请注意,必须在编译QGIS时支持Postgres,否则此提供者不可用:

    1
    2
    3
    4
    5
    6
    uri = QgsDataSourceUri()
    # 设置主机,端口,数据库名称,用户名和密码
    uri.setConnection("localhost", "5432", "dbname", "johny", "xxx")
    # 设置数据库架构,表名,几何列和可选项(WHERE 语句)
    uri.setDataSource("public", "roads", "the_geom", "cityid = 2643", "primary_key_field")
    vlayer = QgsVectorLayer(uri.uri(False), "layer name you like", "postgres")
    

: !!! 提示

1
    `uri.uri(False)`中的`False`参数可以防止扩展认证配置参数,如果你没有使用任何身份验证配置,则此参数不会产生任何差异。
  • CSV或其他分隔的文本文件——打开一个用分号作为分隔符的文件,X坐标使用字段“x”,Y坐标使用字段“y”:

    1
    2
    3
    uri = "file://{}/testdata/delimited_xy.csv?delimiter={}&xField={}&yField={}".format(os.getcwd(), ";", "x", "y")
    vlayer = QgsVectorLayer(uri, "layer name you like", "delimitedtext")
    QgsProject.instance().addMapLayer(vlayer)
    

: !!! 提示

1
2
3
4
5
    提供者的字符串作为一个URL,因此路径必须以file://为前缀。它还允许WKT((well known text)格式的几何作为`x`和`y`的替代字段,并允许指定坐标参考系统。例如:

    ```python
    uri = "file:///some/path/file.csv?delimiter={}&crs=epsg:4723&wktField={}".format(";", "shape")
    ```
  • GPX文件——“gpx”数据提供者从gpx文件中读取轨迹,路线和路点。要打开文件,需要在url中指定类型(track / route / waypoint):
1
2
3
uri = "path/to/gpx/file.gpx?type=track"
vlayer = QgsVectorLayer(uri, "layer name you like", "gpx")
QgsProject.instance().addMapLayer(vlayer)
  • SpatiaLite数据库——与PostGIS数据库类似, QgsDataSourceUri可用于生成数据源标识:
1
2
3
4
5
6
7
8
9
uri = QgsDataSourceUri()
uri.setDatabase('/home/martin/test-2.3.sqlite')
schema = ''
table = 'Towns'
geom_column = 'Geometry'
uri.setDataSource(schema, table, geom_column)
display_name = 'Towns'
vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')
QgsProject.instance().addMapLayer(vlayer)
  • 基于MySQL WKB的几何,通过GDAL——数据源是连接表的字符串:
1
2
3
uri = "MySQL:dbname,host=localhost,port=3306,user=root,password=xxx|layername=my_table"
vlayer = QgsVectorLayer( uri, "my table", "ogr" )
QgsProject.instance().addMapLayer(vlayer)
  • WFS连接:连接使用URI定义并使用WFS提供者:

1
2
uri = "https://demo.geo-solutions.it/geoserver/ows?service=WFS&version=1.1.0&request=GetFeature&typename=geosolutions:regioni"
vlayer = QgsVectorLayer(uri, "my wfs layer", "WFS")
可以使用标准库urllib创建uri:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import urllib

params = {
    'service': 'WFS',
    'version': '1.1.0',
    'request': 'GetFeature',
    'typename': 'geosolutions:regioni',
    'srsname': "EPSG:4326"
}
uri2 = 'https://demo.geo-solutions.it/geoserver/ows?' + urllib.parse.unquote(urllib.parse.urlencode(params))

: !!! 提示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
     可以通过调用[`QgsVectorLayer`](https://qgis.org/pyqgis/master/core/QgsVectorLayer.html#qgis.core.QgsVectorLayer)的 [`setDataSource()`](https://qgis.org/pyqgis/master/core/QgsMapLayer.html#qgis.core.QgsMapLayer.setDataSource) 方法更改现有图层的数据源,如下面例子:

    ```python
    uri = "https://demo.geo-solutions.it/geoserver/ows?service=WFS&version=1.1.0&request=GetFeature&typename=geosolutions:regioni"
    provider_options = QgsDataProvider.ProviderOptions()
    # 使用项目的转换上下文
    provider_options.transformContext = QgsProject.instance().transformContext()
    vlayer.setDataSource(uri, "layer name you like", "WFS", provider_options)

    del(vlayer)
    ```

3.2 栅格图层⚓︎

访问栅格文件,用到了GDAL库。它支持多种文件格式。如果你在打开某些文件时遇到问题,请检查你的GDAL是否支持(默认情况下并非所有格式都可用)。从文件加载栅格,需要指定其文件名和显示名称:

1
2
3
4
5
# 获取tif文件的路径,例如:/home/project/data/srtm.tif 
path_to_tif = "qgis-projects/python_cookbook/data/srtm.tif"
rlayer = QgsRasterLayer(path_to_tif, "SRTM layer name")
if not rlayer.isValid():
    print("图层加载失败!")

geopackage中加载栅格:

1
2
3
4
5
6
7
# 获取geopackage的路径,例如:/home/project/data/data.gpkg 
path_to_gpkg = os.path.join(os.getcwd(), "testdata", "sublayers.gpkg")
# gpkg_raster_layer = "GPKG:/home/project/data/data.gpkg:srtm"
gpkg_raster_layer = "GPKG:" + path_to_gpkg + ":srtm"
rlayer = QgsRasterLayer(gpkg_raster_layer, "layer name you like", "gdal")
if not rlayer.isValid():
    print("图层加载失败!")

与矢量图层类似,可以使用QgisInterface对象的addRasterLayer函数加载栅格图层:

1
iface.addRasterLayer("/path/to/raster/file.tif", "layer name you like")

这将创建一个新图层,并将其添加到当前项目中(使其显示在图层列表中)。

3.2.1 加载PostGIS栅格图层⚓︎

PostGIS栅格图层,类似于PostGIS矢量图层,可以使用URI字符串添加到项目中。为数据库连接参数保留可复用字典是有效的。这样可以轻松编辑适用连接的字典。使用postgresraster提供者的元数据对象将字典编码为URI。之后,可以将栅格图层添加到项目中。

 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
uri_config = {
    # 数据库参数
    'dbname':'gis_db',      # 数据库名称
    'host':'localhost',     # IP地址或者localhost
    'port':'5432',          # 端口
    'sslmode':QgsDataSourceUri.SslDisable, # SslAllow, SslPrefer, SslRequire, SslVerifyCa, SslVerifyFull
    # 如果存储在authcfg或服务中,则不需要用户名和密码
    'authcfg':'QconfigId',  # QGIS认证数据库ID包含连接信息
    'service': None,         # 连接数据库的服务
    'username':None,        # 用户名
    'password':None,        # 密码
    # 数据库表和栅格字段信息
    'schema':'public',      # 数据库架构
    'table':'my_rasters',   # 数据库表名称
    'geometrycolumn':'rast',# 栅格字段名称
    'sql':None,             # WHERE查询语句,应该放在字符串末尾。
    'key':None,             # 数据库表主键
    'srid':None,            # 字符串,指定坐标参考系
    'estimatedmetadata':'False', # A boolean value telling if the metadata is estimated.
    'type':None,            # WKT字符串,指定WKB类型
    'selectatid':None,      # 设置为True可禁用按要素ID进行的选择。
    'options':None,         # 不在此列表中的其他PostgreSQL连接选项。
    'enableTime': None,
    'temporalDefaultTime': None,
    'temporalFieldIndex': None,
    'mode':'2',             # GDAL参数, 2 unions raster tiles, 1 adds tiles separately (may require user input)
}
# 删除空参数
uri_config = {key:val for key, val in uri_config.items() if val is not None}
# 获取数据提供者和配置的元数据
md = QgsProviderRegistry.instance().providerMetadata('postgresraster')
uri = QgsDataSourceUri(md.encodeUri(uri_config))

# 加载栅格图层到项目
rlayer = iface.addRasterLayer(uri.uri(False), "raster layer name", "postgresraster")

3.2.2 加载WCS服务栅格图层:⚓︎

1
2
3
layer_name = 'nurc:mosaic'
uri = "https://demo.geo-solutions.it/geoserver/ows?identifier={}".format(layer_name)
rlayer = QgsRasterLayer(uri, 'my wcs layer', 'wcs')

以下是WCS URI可以包含的参数说明:

WCS URI由 键=值 对组成,分隔符:&。它与URL中的查询字符串格式相同,编码方式相同。QgsDataSourceUri 可以用于构造URI以确保正确编码特殊字符。

  • url(必填):WCS服务器URL。不要在URL中使用VERSION,因为每个版本的WCS对 GetCapabilities 版本使用不同的参数名称,请参阅param版本。
  • identifier(必填):覆盖范围名称
  • time(可选):时间位置或时间段(beginPosition / endPosition / timeResolution)
  • format(可选):支持的格式名称。默认是第一个支持的格式,其名称为tif或第一个支持的格式。
  • crs(可选):CRS格式为AUTHORITY:ID,例如,EPSG:4326。默认为EPSG:4326(如果支持)或第一个支持的CRS。
  • username(可选):基本身份验证的用户名。
  • password(可选):基本身份验证的密码。
  • IgnoreGetMapUrl(可选,hack):如果指定(设置为1),则忽略GetCapabilities公布的GetCoverage URL。如果未正确配置服务器,则可能需要。
  • InvertAxisOrientation(可选,hack):如果指定(设置为1),则在GetCoverage请求中切换轴。如果服务器使用错误的轴顺序,则可能需要地理CRS。
  • IgnoreAxisOrientation(可选,hack):如果指定(设置为1),则不要根据地理CRS的WCS标准反转轴方向。
  • cache(可选):缓存加载控制,如QNetworkRequest :: CacheLoadControl中所述,但如果使用AlwaysCache失败,请求将重新发送为PreferCache。允许的值:AlwaysCache,PreferCache,PreferNetwork,AlwaysNetwork。默认为AlwaysCache。

另外,你可以从WMS服务器加载栅格图层。但是目前无法从API访问GetCapabilities响应——你必须知道所需的图层:

1
2
3
4
urlWithParams = 'url=http://irs.gis-lab.info/?layers=landsat&styles=&format=image/jpeg&crs=EPSG:4326'
rlayer = QgsRasterLayer(urlWithParams, 'some layer name', 'wms')
if not rlayer.isValid():
    print("图层加载失败!")

3.3 QgsProject 实例⚓︎

如果你想使用打开的图层进行渲染,请不要忘记将它们添加到QgsProject实例中。QgsProject实例拥有图层的所有权,可以通过其唯一ID从应用程序的任何部分访问它们。从项目中删除图层时,它也会被删除。用户可以在QGIS接口中删除图层,也可以通过Python使用removeMapLayer()方法删除图层。

使用addMapLayer()方法将图层添加到当前项目:

1
QgsProject.instance().addMapLayer(rlayer)

在绝对位置添加图层:

1
2
3
4
5
6
# 首先添加图层但不显示
QgsProject.instance().addMapLayer(rlayer, False)
# 在项目中获取图层树的根图层组
layerTree = iface.layerTreeCanvasBridge().rootGroup()
# 第一个参数是一个从0开始的数字,-1表示结束
layerTree.insertChildNode(-1, QgsLayerTreeLayer(rlayer))

如果要删除图层,使用removeMapLayer()方法:

1
QgsProject.instance().removeMapLayer(rlayer.id())

在上面的代码中,传递了图层ID(你可以调用图层的id()方法),但是你也可以传递图层对象本身。

获取已加载图层和图层ID的列表,使用mapLayers()方法:

1
QgsProject.instance().mapLayers()