0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

QGIS プラグインの動的ロードと実行

Last updated at Posted at 2019-06-16

この記事は2018年3月くらいに一時公開していたものの再投稿です。

目標

QGIS プラグインから他のプラグインを呼び出してみる」を書いていたらプラグインの動的ロードと組み合わせたら色々できるのではないかと閃いたので試してみたいと思います。
ついでに動的ロードしたプラグイン同士をシグナルで繋げて動かしてみよう。

下準備

Githubにテスト用のダミープラグインを用意しました。ダウンロードはこちらです。
QGIS3のプラグインフォルダにaaa_pluginbbb_pluginというフォルダを作成してその中にダウンロードしたソースファイルをコピーしておきます。

Pythonコンソールから動的ロード

QGISの[プラグイン]メニューから[Pythonコンソール]を起動します。
まずは現在読み込まれているプラグインリストを確認してみましょう。

>>> qgis.utils.plugins.keys()
dict_keys(['pluginbuilder3', 'plugin_reloader', 'db_manager', 'processing'])

aaa_pluginbbb_pluginも読み込まれていませんね。
ではaaa_pluginをロードしてみます。

>>> plugin_name = 'aaa_plugin'
>>> qgis.utils.loadPlugin(plugin_name)
True
>>> qgis.utils.startPlugin(plugin_name)
True
>>> qgis.utils.plugins.keys()
dict_keys(['pluginbuilder3', 'plugin_reloader', 'db_manager', 'processing', 'aaa_plugin'])

aaa_pluginがロードされてpluginsに追加されていることが確認できました。
ではaaa_pluginのメソッドを叩いてみましょう。

>>> plugin = qgis.utils.plugins[plugin_name]
>>> plugin.handle_trigger('dynamic_load')

引数に与えた文字列がメッセージダイアログで表示されました。
問題なくプラグインのロードができたようです。

プラグイン内で動的ロード&シグナル

今度はプラグイン(aaa_plugin)内で他のプラグイン(bbb_plugin)をロードして、ロード先からロード元のシグナルにコネクトして、ロード元のシグナルを受けてロード先がメッセージを表示するってのをやってみます。
言葉で書くと訳が判らないのでなんちゃってシーケンス図を貼っておきます。
Dynamic Sequence.png

プラグインを動的ロードするloadAndExecとカスタムシグナルを使ってシグナルを受け渡す、emitMessageconnectTriggerを追加します。
Gitからソースをダウンロードした方は、適宜コメント箇所を外してください。

カスタムシグナルの使い方は以下の記事を参考にさせていただきました。
PyQt5とpython3によるGUIプログラミング[1]

ソースはこんな感じになります。

aaa.py
import os
from PyQt5.QtCore import QSettings, QTranslator, qVersion, QCoreApplication, pyqtSignal, QObject
from PyQt5.QtGui import QIcon
from qgis.utils import plugins, loadPlugin, startPlugin
from PyQt5.QtWidgets import QAction, QMessageBox

# Initialize Qt resources from file resources.py
from .resources import *

class CustomSignal(QObject):
    mySignal = pyqtSignal(str)

class AAA:
    myObject = CustomSignal()
    """QGIS Plugin Implementation."""
    def __init__(self, iface):
        self.iface = iface
        self.plugin_instance = None

    def initGui(self):
        pass

    def unload(self):
        pass

    def run(self):
        pass

    def loadAndExec(self, plugin_name, function_name, function_param):
        plugin_list = plugins.keys()
        if not plugin_name in plugin_list:
            # ロード実行
            try:
              loadPlugin(plugin_name)
              startPlugin(plugin_name)
              self.plugin_instance = plugins[plugin_name]
              # メソッド実行
              eval("self.plugin_instance." + function_name + "('" + function_param + "')")
            except:
                QMessageBox.critical(self.iface.mainWindow(), 'error', "%s error" % plugin_name)

    def connectTrigger(self, plugin_name):
        self.parent_plugin_instance = plugins[plugin_name]
        self.parent_plugin_instance.myObject.mySignal.connect(self.handle_trigger)
        
    def handle_trigger(self, message):
        QMessageBox.information(self.iface.mainWindow(), 'info', "%s" % message)

    def emitMessage(self, message):
        self.myObject.mySignal.emit(message)

では一旦プラグインの状態をリセットしたいのでQGISを再起動してからPythonコンソールを開き直します。
aaa_pluginをロードしてインスタンスを取得するところまでは同じですが、今度はloadAndExecを実行してbbb_pluginをロードしてconnectTriggerメソッド実行させます。

>>> plugin_name = 'aaa_plugin'
>>> qgis.utils.loadPlugin(plugin_name)
True
>>> qgis.utils.startPlugin(plugin_name)
True
>>> plugin = qgis.utils.plugins[plugin_name]
>>> plugin.loadAndExec('bbb_plugin', 'connectTrigger', plugin_name)

これでbbb_pluginからaaa_pluginにコネクトできました。
aaa_pluginのシグナルを起こしてみましょう。

>>> plugin.emitMessage('test')

引数に与えた文字列がメッセージダイアログで表示されました。
目的達成です。

最後に

良い感じに連携が取れることが確認できました。
QGISを使った小中規模の業務システムならこの仕組みを使うことで柔軟な設計ができそうです。

以上です。

本記事のライセンス
クリエイティブ・コモンズ・ライセンス
この記事は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?