PyQGIS リレーションのサンプル


どんな動きをするの?

このサンプルでは、国土数値情報ダウンロードサービスからダウンロードできる行政区域避難所を使います。

f:id:Chiakikun:20200606202451p:plain

プラグインを実行すると、上のようにリレーションが作られます。

 

f:id:Chiakikun:20200606202506p:plain

プラグインを実行したままで、行政区域の地物を選択すると...

 

f:id:Chiakikun:20200606202518p:plain

選択した地物と関係ある避難所の地物が選択状態になり、属性テーブルが表示されます。


コード

from qgis.PyQt import QtWidgets
from qgis.PyQt.Qt import QSettings
import qgis
from qgis.core import *
from qgis.gui  import *

class RelationSample:

    def __init__(self, iface, parentLayer, parentField, childLayer, childField):

        self.iface = iface

        self.rel = QgsRelation()
        self.rel.setReferencingLayer(childLayer.id())
        self.rel.setReferencedLayer(parentLayer.id())
        self.rel.addFieldPair(childField, parentField)
        self.rel.setId('適当なID')
        self.rel.setName('適当な名前')
        QgsProject.instance().relationManager().addRelation(self.rel)

        self.parent = parentLayer
        self.parent.selectionChanged.connect(self.showChildren)


    def showChildren(self):
        parent = self.rel.referencedLayer()
        child = self.rel.referencingLayer()

        features = parent.selectedFeatures()
        if len(features) == 0:
            return

        child.removeSelection() # クリアしないと、属性テーブルに余計に表示されるから 
        for c in self.rel.getRelatedFeatures(features[0]):
            child.select(c.id())

        selectedlayer = self.iface.activeLayer() # 退避
        try:
            # このプログラム実行中は属性テーブルは選択中のフューチャーしか表示しない
            self.oldsetting = QSettings().value('/Qgis/attributeTableBehaviour')
            QSettings().setValue('/Qgis/attributeTableBehavior', 'ShowSelected')

            self.iface.setActiveLayer(child)
            self.iface.mainWindow().findChild(QtWidgets.QAction, 'mActionOpenTable' ).trigger()
        finally:
            self.iface.setActiveLayer(selectedlayer) # 戻す
            QSettings().setValue('/Qgis/attributeTableBehavior', self.oldsetting)


    def __del__(self):
        QgsProject.instance().relationManager().removeRelation(self.rel)
        self.parent.selectionChanged.disconnect(self.showChildren)

ソースはこちら


使い方

例として、ここからダウンロードできるサンプルプラグインに追加します。

nodialog_skelton.pyと同じフォルダにソースを置いて、インポート部分に次のコードを追記します。

from .relationsample import RelationSample

nodialog_skelton.pyのstartを次のコードに書き換えます。

    def start(self):
        # 国土数値情報ダウンロードサービスからダウンロードできる行政区域と避難所を使う場合
        parent = QgsProject.instance().mapLayersByName('行政区域')[0]
        child =QgsProject.instance().mapLayersByName('避難所')[0]
        self.rel = RelationSample(self.iface, parent, 'N03_007', child, 'p20_001')

nodialog_skelton.pyのfinishを次のコードに書き換えます。

    def finish(self):
        self.rel = None

このようになればOKです。

~略~
from .relationsample import RelationSample

class NodialogSkelton(qgis.gui.QgsMapTool):

    def start(self):
        parent = QgsProject.instance().mapLayersByName('行政区域')[0]
        child =QgsProject.instance().mapLayersByName('避難所')[0]
        self.rel = RelationSample(self.iface, parent, 'N03_007', child, 'p20_001')
        
        
    def finish(self):
        self.rel = None
~略~

 


最後までご覧頂き、ありがとうございました