LoginSignup
14
3
お題は不問!Qiita Engineer Festa 2023で記事投稿!

PyQGISでレイヤパネルの操作を試した時のメモ

Posted at

はじめに

QGISでプラグインを作成していると、レイヤパネルを操作したい場面が多々あります。
この記事は、PyQGISでレイヤパネルを操作する方法について調べた時の覚書です。

前提

レイヤパネルには、以下のようにレイヤが追加されていることを前提とします。
image.png

  • ルート
    • 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)

image.png

レイヤを削除する

layer = QgsProject.instance().mapLayersByName('TEST')[0]
QgsProject.instance().removeMapLayer(layer.id())

image.png

指定した位置にレイヤを追加する

layer = QgsVectorLayer("Point?crs=EPSG:4326", "TEST", "memory")
layerTree = iface.layerTreeCanvasBridge().rootGroup()
QgsProject.instance().addMapLayer(layer, False)
# 上から3番目の位置にレイヤを追加
layerTree.insertChildNode(2, QgsLayerTreeLayer(layer))

image.png

指定したレイヤの真下にレイヤを追加

# 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)

image.png

レイヤをグループ内に移動

# 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)

image.png

グループを追加する

root = QgsProject.instance().layerTreeRoot()
node_group = QgsLayerTreeGroup("Group")
root.addChildNode(node_group)

image.png

グループを削除する

root = QgsProject.instance().layerTreeRoot()
node_group = root.findGroup("Group")
root.removeChildNode(node_group)

image.png

レイヤとグループの表示・非表示を変更する

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)

image.png

グループの展開・折り畳む

my_group = QgsProject.instance().layerTreeRoot().findGroup("背景地図")
my_group.setExpanded(False)

image.png

参考

14
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
3