はじめに
QGISでプラグインを作成していると、レイヤパネルを操作したい場面が多々あります。
この記事は、PyQGISでレイヤパネルを操作する方法について調べた時の覚書です。
前提
レイヤパネルには、以下のようにレイヤが追加されていることを前提とします。
- ルート
- QgsLayerTreeオブジェクト
- これが最上位のオブジェクト
- ルートの子
- QgsLayerTreeLayer
- QgsLayerTreeGroup
ルートの子を取得する
root = QgsProject.instance().layerTreeRoot()
print(root)
print(root.children())
# <qgis._core.QgsLayerTree object at 0x0000600001e61200>
# [<QgsLayerTreeGroup: 交通>, <QgsLayerTreeLayer: 海岸線>, <QgsLayerTreeLayer: 行政界>, <QgsLayerTreeLayer: el256>, <QgsLayerTreeLayer: lu>, <QgsLayerTreeGroup: 背景地図>]
ルートの最初の子ノードにアクセス
root = QgsProject.instance().layerTreeRoot()
child0 = root.children()[0]
print(child0)
print(type(child0))
print(isinstance(child0, QgsLayerTreeLayer))
print(child0.parent())
print(root.parent())
# <QgsLayerTreeGroup: 交通>
# <class 'qgis._core.QgsLayerTreeGroup'>
# False
# <qgis._core.QgsLayerTree object at 0x0000600001e61200>
# None
グループとそのノードを取得する
from qgis.core import QgsLayerTreeGroup, QgsLayerTreeLayer
def get_group_layers(group):
print('- group: ' + group.name())
for child in group.children():
if isinstance(child, QgsLayerTreeGroup):
# Recursive call to get nested groups
get_group_layers(child)
else:
print(' - layer: ' + child.name())
root = QgsProject.instance().layerTreeRoot()
for child in root.children():
if isinstance(child, QgsLayerTreeGroup):
get_group_layers(child)
elif isinstance(child, QgsLayerTreeLayer):
print ('- layer: ' + child.name())
# - group: 交通
# - layer: 空港
# - layer: 道路
# - group: 鉄道
# - layer: 線路
# - layer: 駅
# - layer: 海岸線
# - layer: 行政界
# - layer: el256
# - layer: lu
# - group: 背景地図
# - layer: Mapzen Global Terrain
# - layer: OpenStreetMap
ルートからツリーレイヤーを取得する
ids = root.findLayerIds()
print (ids)
print (root.findLayers())
print (root.findLayer(ids[0]))
#['airp_jpn_19313c29_cd74_4b31_b8bf_b5a4743a813e', 'roadl_jpn_42fbebf7_2896_48c6_9b2c_0c6968b07c12', 'raill_jpn_a5c85270_8b05_4fcd_a3cd_11175d18f21f', 'N02_22_Station_ed27438c_f217_4b83_96e7_a1b398b838fd', 'coastl_jpn_2767651f_9d89_464b_9a5c_60ec25c2026f', 'bnda_1_1_33e9c638_1e23_4073_8f00_3d2bd4e6ee7e', 'el256_82f42cac_5844_4620_bf1d_0363006ff40d', 'lu_fd1b9e12_eb64_418b_879f_27516f33d80f', 'Mapzen_Global_Terrain_8174a9f5_d71c_47e0_95af_32d4e5c59b8f', 'OpenStreetMap_17b01ae4_e89a_46c1_bba9_52fcd4163918']
# [<QgsLayerTreeLayer: 空港>, <QgsLayerTreeLayer: 道路>, <QgsLayerTreeLayer: 線路>, <QgsLayerTreeLayer: 駅>, <QgsLayerTreeLayer: 海岸線>, <QgsLayerTreeLayer: 行政界>, <QgsLayerTreeLayer: el256>, <QgsLayerTreeLayer: lu>, <QgsLayerTreeLayer: Mapzen Global Terrain>, <QgsLayerTreeLayer: OpenStreetMap>]
# <QgsLayerTreeLayer: 空港>
親ノードを取得する
layer = QgsProject.instance().mapLayersByName("線路")[0]
root = QgsProject.instance().layerTreeRoot()
my_layer = root.findLayer(layer.id())
parent = my_layer.parent()
print("myLayer" ,myLayer)
print("p1:", parent)
print("p2:", parent.parent())
print("p3:", parent.parent().parent())
print("p4:", parent.parent().parent().parent())
# myLayer <QgsLayerTreeLayer: 線路>
# p1: <QgsLayerTreeGroup: 鉄道>
# p2: <QgsLayerTreeGroup: 交通>
# p3: <qgis._core.QgsLayerTree object at 0x0000600001e61200>
# p4: None
グループを取得する
groups = QgsProject().instance().layerTreeRoot().findGroups()
group_names = list(map(lambda g: g.name(), groups))
traffic_group = root.findGroup("交通")
railroad_group = root.findGroup("鉄道")
print(groups)
print(group_names)
print(traffic_group)
print(railroad_group)
# [<QgsLayerTreeGroup: 交通>, <QgsLayerTreeGroup: 背景地図>]
# ['交通', '背景地図']
# <QgsLayerTreeGroup: 交通>
# <QgsLayerTreeGroup: 鉄道>
レイヤIDからツリーレイヤを取得する
layer = QgsProject.instance().mapLayersByName('線路')[0]
railroad_layer = root.findLayer(layer.id())
# <QgsLayerTreeLayer: 線路>
レイヤを追加する
layer = QgsVectorLayer("Point?crs=EPSG:4326", "TEST", "memory")
# falseをつけるとレイヤパネルの最下部に追加される
QgsProject.instance().addMapLayer(layer, False)
node_layer = root.addLayer(layer)
レイヤを削除する
layer = QgsProject.instance().mapLayersByName('TEST')[0]
QgsProject.instance().removeMapLayer(layer.id())
指定した位置にレイヤを追加する
layer = QgsVectorLayer("Point?crs=EPSG:4326", "TEST", "memory")
layerTree = iface.layerTreeCanvasBridge().rootGroup()
QgsProject.instance().addMapLayer(layer, False)
# 上から3番目の位置にレイヤを追加
layerTree.insertChildNode(2, QgsLayerTreeLayer(layer))
指定したレイヤの真下にレイヤを追加
# el256の下にレイヤを追加する
ref_layer = QgsProject.instance().mapLayersByName("el256")[0]
insert_layer = QgsVectorLayer("Point", "TEST2", "memory")
root = QgsProject.instance().layerTreeRoot()
QgsProject.instance().addMapLayer(insert_layer, False)
QgsLayerTreeUtils.insertLayerBelow(root, ref_layer, insert_layer)
レイヤをグループ内に移動
# TESTレイヤを交通グループ内に移動する
layer = QgsProject.instance().mapLayersByName("TEST")[0]
root = QgsProject.instance().layerTreeRoot()
my_layer = root.findLayer(layer.id())
my_clone = my_layer.clone()
parent = my_layer.parent()
my_group = root.findGroup("交通")
my_group.insertChildNode(0, my_clone)
parent.removeChildNode(my_layer)
グループを追加する
root = QgsProject.instance().layerTreeRoot()
node_group = QgsLayerTreeGroup("Group")
root.addChildNode(node_group)
グループを削除する
root = QgsProject.instance().layerTreeRoot()
node_group = root.findGroup("Group")
root.removeChildNode(node_group)
レイヤとグループの表示・非表示を変更する
root = QgsProject.instance().layerTreeRoot()
layer = QgsProject.instance().mapLayersByName('TEST')[0]
target_layer = root.findLayer(layer.id())
target_group = root.findGroup("交通")
# レイヤを非表示
target_layer.setItemVisibilityChecked(False)
# グループを非表示
target_group.setItemVisibilityChecked(False)
グループの展開・折り畳む
my_group = QgsProject.instance().layerTreeRoot().findGroup("背景地図")
my_group.setExpanded(False)