3. 加载层

提示

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

import os # This is is needed in the pyqgis console also
from qgis.core import (
    QgsVectorLayer
)

让我们打开一些包含数据的层。QGIS可以识别矢量层和栅格层。此外,自定义层类型是可用的,但我们不会在这里讨论它们。

3.1. 矢量层

要创建向量层实例并将其添加到项目中,请指定层的数据源标识符、层的名称和提供程序的名称:

 1# get the path to the shapefile e.g. /home/project/data/ports.shp
 2path_to_airports_layer = "testdata/airports.shp"
 3
 4# The format is:
 5# vlayer = QgsVectorLayer(data_source, layer_name, provider_name)
 6
 7vlayer = QgsVectorLayer(path_to_airports_layer, "Airports layer", "ogr")
 8if not vlayer.isValid():
 9    print("Layer failed to load!")
10else:
11    QgsProject.instance().addMapLayer(vlayer)

数据源标识符是一个字符串,它特定于每个矢量数据提供程序。层的名称在层列表小工具中使用。检查是否已成功加载层非常重要。如果不是,则返回无效的Layer实例。

对于Geopackage向量层:

 1# get the path to a geopackage  e.g. /usr/share/qgis/resources/data/world_map.gpkg
 2path_to_gpkg = os.path.join(QgsApplication.pkgDataPath(), "resources", "data", "world_map.gpkg")
 3# append the layername part
 4gpkg_countries_layer = path_to_gpkg + "|layername=countries"
 5# e.g. gpkg_places_layer = "/usr/share/qgis/resources/data/world_map.gpkg|layername=countries"
 6vlayer = QgsVectorLayer(gpkg_countries_layer, "Countries layer", "ogr")
 7if not vlayer.isValid():
 8    print("Layer failed to load!")
 9else:
10    QgsProject.instance().addMapLayer(vlayer)

在QGIS中打开和显示矢量图层的最快方法是 addVectorLayer() 的方法。 QgisInterface

vlayer = iface.addVectorLayer(path_to_airports_layer, "Airports layer", "ogr")
if not vlayer:
  print("Layer failed to load!")

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

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

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

    • 对于Shapefile:

      vlayer = QgsVectorLayer("testdata/airports.shp", "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
    • 对于DXF(请注意数据源URI中的内部选项):

      uri = "testdata/sample.dxf|layername=entities|geometrytype=Polygon"
      vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
  • PostGIS数据库-数据源是一个字符串,其中包含创建到PostgreSQL数据库的连接所需的所有信息。

    QgsDataSourceUri 类可以为您生成此字符串。请注意,QGIS必须使用Postgres支持进行编译,否则此提供程序不可用:

    1uri = QgsDataSourceUri()
    2# set host name, port, database name, username and password
    3uri.setConnection("localhost", "5432", "dbname", "johny", "xxx")
    4# set database schema, table name, geometry column and optionally
    5# subset (WHERE clause)
    6uri.setDataSource("public", "roads", "the_geom", "cityid = 2643", "primary_key_field")
    7
    8vlayer = QgsVectorLayer(uri.uri(False), "layer name you like", "postgres")
    

    备注

    这个 False 参数传递给 uri.uri(False) 防止扩展身份验证配置参数,如果您未使用任何身份验证配置,则此参数不会产生任何影响。

  • CSV或其他带分隔符的文本文件-要打开以分号作为分隔符、以字段“x”作为X坐标、以字段“y”作为Y坐标的文件,您可以使用如下内容:

    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)
    

    备注

    提供程序字符串的结构为URL,因此路径必须以 file:// 。此外,它还允许WKT(熟知文本)格式化几何作为替代 xy 字段,并允许指定坐标参考系。例如:

    uri = "file:///some/path/file.csv?delimiter={}&crs=epsg:4723&wktField={}".format(";", "shape")
    
  • GPX文件-“GPX”数据提供者从GPX文件中读取轨迹、路线和路点。要打开文件,需要将类型(轨迹/路线/路点)指定为url的一部分:

    uri = "testdata/layers.gpx?type=track"
    vlayer = QgsVectorLayer(uri, "layer name you like", "gpx")
    QgsProject.instance().addMapLayer(vlayer)
    
  • SpatiaLite数据库-类似于PostGIS数据库, QgsDataSourceUri 可用于生成数据源标识符:

     1uri = QgsDataSourceUri()
     2uri.setDatabase('/home/martin/test-2.3.sqlite')
     3schema = ''
     4table = 'Towns'
     5geom_column = 'Geometry'
     6uri.setDataSource(schema, table, geom_column)
     7
     8display_name = 'Towns'
     9vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')
    10QgsProject.instance().addMapLayer(vlayer)
    
  • 基于MySQL WKB的几何,通过GDAL-数据源是表的连接字符串:

    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 提供商:

    uri = "https://demo.mapserver.org/cgi-bin/wfs?service=WFS&version=2.0.0&request=GetFeature&typename=ms:cities"
    vlayer = QgsVectorLayer(uri, "my wfs layer", "WFS")
    

    URI可以使用标准的 urllib 库:

     1import urllib
     2
     3params = {
     4    'service': 'WFS',
     5    'version': '2.0.0',
     6    'request': 'GetFeature',
     7    'typename': 'ms:cities',
     8    'srsname': "EPSG:4326"
     9}
    10uri2 = 'https://demo.mapserver.org/cgi-bin/wfs?' + urllib.parse.unquote(urllib.parse.urlencode(params))
    

备注

可以通过调用以下方法更改现有图层的数据源 setDataSource() 在一个 QgsVectorLayer 实例,如下例所示:

1uri = "https://demo.mapserver.org/cgi-bin/wfs?service=WFS&version=2.0.0&request=GetFeature&typename=ms:cities"
2provider_options = QgsDataProvider.ProviderOptions()
3# Use project's transform context
4provider_options.transformContext = QgsProject.instance().transformContext()
5vlayer.setDataSource(uri, "layer name you like", "WFS", provider_options)
6
7del(vlayer)

3.2. 栅格图层

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

1# get the path to a tif file  e.g. /home/project/data/srtm.tif
2path_to_tif = "qgis-projects/python_cookbook/data/srtm.tif"
3rlayer = QgsRasterLayer(path_to_tif, "SRTM layer name")
4if not rlayer.isValid():
5    print("Layer failed to load!")

要从地理包加载栅格,请执行以下操作:

1# get the path to a geopackage  e.g. /home/project/data/data.gpkg
2path_to_gpkg = os.path.join(os.getcwd(), "testdata", "sublayers.gpkg")
3# gpkg_raster_layer = "GPKG:/home/project/data/data.gpkg:srtm"
4gpkg_raster_layer = "GPKG:" + path_to_gpkg + ":srtm"
5
6rlayer = QgsRasterLayer(gpkg_raster_layer, "layer name you like", "gdal")
7
8if not rlayer.isValid():
9    print("Layer failed to load!")

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

iface.addRasterLayer(path_to_tif, "layer name you like")

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

要加载PostGIS栅格,请执行以下操作:

与PostGIS矢量类似,可以使用URI字符串将PostGIS栅格添加到项目中。为数据库连接参数保留一个可重复使用的字符串字典是有效的。这使得为适用的连接编辑词典变得很容易。然后使用‘postgresraster’提供程序元数据对象将词典编码到URI中。之后,可以将栅格添加到项目中。

 1uri_config = {
 2    # database parameters
 3    'dbname':'gis_db',      # The PostgreSQL database to connect to.
 4    'host':'localhost',     # The host IP address or localhost.
 5    'port':'5432',          # The port to connect on.
 6    'sslmode':QgsDataSourceUri.SslDisable, # SslAllow, SslPrefer, SslRequire, SslVerifyCa, SslVerifyFull
 7    # user and password are not needed if stored in the authcfg or service
 8    'authcfg':'QconfigId',  # The QGIS athentication database ID holding connection details.
 9    'service': None,         # The PostgreSQL service to be used for connection to the database.
10    'username':None,        # The PostgreSQL user name.
11    'password':None,        # The PostgreSQL password for the user.
12    # table and raster column details
13    'schema':'public',      # The database schema that the table is located in.
14    'table':'my_rasters',   # The database table to be loaded.
15    'geometrycolumn':'rast',# raster column in PostGIS table
16    'sql':None,             # An SQL WHERE clause. It should be placed at the end of the string.
17    'key':None,             # A key column from the table.
18    'srid':None,            # A string designating the SRID of the coordinate reference system.
19    'estimatedmetadata':'False', # A boolean value telling if the metadata is estimated.
20    'type':None,            # A WKT string designating the WKB Type.
21    'selectatid':None,      # Set to True to disable selection by feature ID.
22    'options':None,         # other PostgreSQL connection options not in this list.
23    'enableTime': None,
24    'temporalDefaultTime': None,
25    'temporalFieldIndex': None,
26    'mode':'2',             # GDAL 'mode' parameter, 2 unions raster tiles, 1 adds tiles separately (may require user input)
27}
28# remove any NULL parameters
29uri_config = {key:val for key, val in uri_config.items() if val is not None}
30# get the metadata for the raster provider and configure the URI
31md = QgsProviderRegistry.instance().providerMetadata('postgresraster')
32uri = QgsDataSourceUri(md.encodeUri(uri_config))
33
34# the raster can then be loaded into the project
35rlayer = iface.addRasterLayer(uri.uri(False), "raster layer name", "postgresraster")

也可以从WCS服务创建栅格图层:

layer_name = 'modis'
url = "https://demo.mapserver.org/cgi-bin/wcs?identifier={}".format(layer_name)
rlayer = QgsRasterLayer(uri, 'my wcs layer', 'wcs')

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

WCS URI由以下部分组成 key=value 由分隔的对 & 。它的格式与URL中的查询字符串相同,编码方式也相同。 QgsDataSourceUri 应用于构造URI,以确保对特殊字符进行正确编码。

  • url (必需):WCS服务器URL。请勿在URL中使用版本,因为每个版本的WCS使用不同的参数名称 GetCapabilities 版本,请参阅参数版本。

  • identifier (必填):覆盖范围名称

  • time (可选):时间位置或时间段(开始位置/结束位置 [/timeResolution] )

  • format (可选):支持的格式名称。默认格式是名称中带有tif的第一个支持的格式或第一个支持的格式。

  • crs (可选):CRS格式为AUTHORITY:ID,例如EPSG:4326。默认为EPSG:4326(如果支持)或第一个支持的CRS。

  • username (可选):基本身份验证的用户名。

  • password (可选):基本身份验证的密码。

  • IgnoreGetMapUrl (可选,Hack):如果指定(设置为1),则忽略GetCapables通告的GetCoverage URL。如果服务器配置不正确,则可能需要。

  • InvertAxisOrientation (可选,Hack):如果指定(设置为1),则切换GetCoverage请求中的轴。如果服务器使用错误的轴顺序,则可能需要对地理CRS执行此操作。

  • IgnoreAxisOrientation (可选,HACK):如果指定(设置为1),则不会根据地理CRS的WCS标准反转轴方向。

  • cache (可选):缓存加载控制,如QNetworkRequest::CacheLoadControl中所述,但如果使用Always缓存失败,则请求将作为PferCache重新发送。允许值:Alway sCache、PferCache、PferNetwork、Alway sNetwork。默认设置为Always缓存。

或者,也可以从WMS服务器加载栅格图层。然而,目前无法从API访问GetCapability响应-您必须知道您想要什么层:

urlWithParams = "crs=EPSG:4326&format=image/png&layers=continents&styles&url=https://demo.mapserver.org/cgi-bin/wms"
rlayer = QgsRasterLayer(urlWithParams, 'some layer name', 'wms')
if not rlayer.isValid():
  print("Layer failed to load!")

3.3. QgsProject实例

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

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

QgsProject.instance().addMapLayer(rlayer)

要在绝对位置添加层,请执行以下操作:

1# first add the layer without showing it
2QgsProject.instance().addMapLayer(rlayer, False)
3# obtain the layer tree of the top-level group in the project
4layerTree = iface.layerTreeCanvasBridge().rootGroup()
5# the position is a number starting from 0, with -1 an alias for the end
6layerTree.insertChildNode(-1, QgsLayerTreeLayer(rlayer))

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

# QgsProject.instance().removeMapLayer(layer_id)
QgsProject.instance().removeMapLayer(rlayer.id())

在上面的代码中,传递了层id(您可以通过调用 id() 方法),但也可以传递Layer对象本身。

有关已加载的层和层ID的列表,请使用 mapLayers() 方法:

QgsProject.instance().mapLayers()