这一节中所有的代码,如果不在QGIS命令行中执行,都需要导入如下包库

from qgis.core import (
    QgsProject,
    QgsVectorLayer,
)

4. 访问目录(TOC)

您可以使用不同的类访问目录中加载的所有层,并使用它们检索信息:

4.1. QgsProject类

You can use QgsProject to retrieve information about the TOC and all the layers loaded.

您必须创建一个 QgsProjectinstance ,并使用其方法获取加载的图层。

主要方法是:meth:mapLayers() <qgis.core.QgsProject.mapLayers>。它将返回已加载图层的字典。

layers = QgsProject.instance().mapLayers()
print(layers)
{'countries_89ae1b0f_f41b_4f42_bca4_caf55ddbe4b6': <QgsMapLayer: 'countries' (ogr)>}

字典 ``keys``是唯一的图层id,而``values``是相关的对象。

现在可以直接获得有关图层的任何其他信息:

1
2
3
4
5
6
7
8
# list of layer names using list comprehension
l = [layer.name() for layer in QgsProject.instance().mapLayers().values()]
# dictionary with key = layer name and value = layer object
layers_list = {}
for l in QgsProject.instance().mapLayers().values():
  layers_list[l.name()] = l

print(layers_list)
{'countries': <QgsMapLayer: 'countries' (ogr)>}

也可以使用图层名来查询目录。

country_layer = QgsProject.instance().mapLayersByName("countries")[0]

注解

返回一个包含所有匹配图层的列表,我们使用``[0]``索引来获取该名称的第一个图层。

4.2. 类QgsLayerTreeGroup

图层树是一种经典的树结构,由节点组成。当前有两种节点:组节点(QgsLayerTreeGroup)和图层节点(QgsLayerTreeLayer)。

注解

想了解更多信息,可以阅读Martin Dobias的博客文章: Part 1 Part 2 Part 3

使用:class:`QgsProject <qgis.core.QgsProject>`的:meth:`layerTreeRoot() <qgis.core.QgsProject.layerTreeRoot>`方法可以方便地访问项目图层树:

root = QgsProject.instance().layerTreeRoot()

``root``是组节点,有 子节点

root.children()

返回直接子节点的列表。子组应该从它们自己的直接父级节点访问。

我们可以检索其中一个子节点:

child0 = root.children()[0]
print(child0)
<qgis._core.QgsLayerTreeLayer object at 0x7f1e1ea54168>

也可以用唯一 (unique) ``id``来检索图层:

ids = root.findLayerIds()
# access the first layer of the ids list
root.findLayer(ids[0])

也可以用组名称来查找组:

root.findGroup('Group Name')

QgsLayerTreeGroup 有许多其他有用的方法,可以用来获取更多关于目录的信息:

# list of all the checked layers in the TOC
checked_layers = root.checkedLayers()
print(checked_layers)
[<QgsMapLayer: 'countries' (ogr)>]

现在,我们来给项目图层树增加一些图层。有两种方法:

  1. **显式添加**使用: addLayer() 或者 :meth:`insertLayer() <qgis.core.QgsLayerTreeGroup.insertLayer>`函数:

    1
    2
    3
    4
    5
    6
    # create a temporary layer
    layer1 = QgsVectorLayer("path_to_layer", "Layer 1", "memory")
    # add the layer to the legend, last position
    root.addLayer(layer1)
    # add the layer at given position
    root.insertLayer(5, layer1)
    
  2. 隐式增加:因为项目的图层树是连接到图层注册表的,所以添加一个图层到地图图层注册表就可以了:

    QgsProject.instance().addMapLayer(layer1)
    

您可以很容易地在 QgsVectorLayerQgsLayerTreeLayer 之间转换:

node_layer = root.findLayer(country_layer.id())
print("Layer node:", node_layer)
print("Map layer:", node_layer.layer())
Layer node: <qgis._core.QgsLayerTreeLayer object at 0x7fecceb46ca8>
Map layer: <QgsMapLayer: 'countries' (ogr)>

可以用方法 addGroup() 来增加组节点。在下面的例子中,前者会在目录的末尾加入一个组节点,而对于后者,您可以在现有组中添加另一个组:

node_group1 = root.addGroup('Simple Group')
# add a sub-group to Simple Group
node_subgroup1 = node_group1.addGroup("I'm a sub group")

很多有用的方法可以用于移动节点和组。

移动一个现有的节点需要三个步骤:

  1. 克隆现有节点

  2. 将克隆节点移动到所需位置

  3. 删除原始节点

1
2
3
4
5
6
# clone the group
cloned_group1 = node_group1.clone()
# move the node (along with sub-groups and layers) to the top
root.insertChildNode(0, cloned_group1)
# remove the original node
root.removeChildNode(node_group1)

在图例中移动一个图层有点“复杂”:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# get a QgsVectorLayer
vl = QgsProject.instance().mapLayersByName("countries")[0]
# create a QgsLayerTreeLayer object from vl by its id
myvl = root.findLayer(vl.id())
# clone the myvl QgsLayerTreeLayer object
myvlclone = myvl.clone()
# get the parent. If None (layer is not in group) returns ''
parent = myvl.parent()
# move the cloned layer to the top (0)
parent.insertChildNode(0, myvlclone)
# remove the original myvl
root.removeChildNode(myvl)

或者将它移动到一个现有的组:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# get a QgsVectorLayer
vl = QgsProject.instance().mapLayersByName("countries")[0]
# create a QgsLayerTreeLayer object from vl by its id
myvl = root.findLayer(vl.id())
# clone the myvl QgsLayerTreeLayer object
myvlclone = myvl.clone()
# create a new group
group1 = root.addGroup("Group1")
# get the parent. If None (layer is not in group) returns ''
parent = myvl.parent()
# move the cloned layer to the top (0)
group1.insertChildNode(0, myvlclone)
# remove the QgsLayerTreeLayer from its parent
parent.removeChildNode(myvl)

一些可以用来修改组和图层的其他方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
node_group1 = root.findGroup("Group1")
# change the name of the group
node_group1.setName("Group X")
node_layer2 = root.findLayer(country_layer.id())
# change the name of the layer
node_layer2.setName("Layer X")
# change the visibility of a layer
node_group1.setItemVisibilityChecked(True)
node_layer2.setItemVisibilityChecked(False)
# expand/collapse the group view
node_group1.setExpanded(True)
node_group1.setExpanded(False)