画像




画像






画像






この記事は、「Qt Advent Calendar 2018」の23日目の記事です。




PyQt5とQtDesignerを利用した、QGIS3系プラグインの構築方法を紹介してみました!




構築した環境をGitHubに公開しました。
QGIS3Plugin-Starter




今回は、下記の流れで紹介していきます。

①QtDesignerでuiファイルを準備
②uiファイルをpythonファイルに変換
③qrcファイルをpythonファイルに変換
④QGISプラグインファイル一式を構築
⑤QGISで確認




全体構成

画像






①QtDesignerでuiファイルを準備


QGISに同封されているQtDesignerを起動。

画像




Widget選択 → 作成。

画像




Widgetが作成される。

画像




ボタンを追加してみる。

画像




サイズと名称を変更して2つにコピーしてみる。今回はobjectNameもそれぞれ固定とする。

画像




ついでにテキストボックスも追加してみる。

画像




サンプルのUIを名前を付けて保存する。

画像




ファイル名称は「Sample_Menu_02_Base.ui」として「./_resouce/ui」に保存。

画像






②uiファイルをpythonファイルに変換


「OSGeo4W Shell」を起動。

画像




「./_resouce/ui/ui.bat」を実行して、uiファイルをpythonファイルに変換します。


./_resouce/ui


ui.bat


@echo off
call "C:\ProgramFolder\QGIS30402\bin\o4w_env.bat"
call "C:\ProgramFolder\QGIS30402\bin\qt5_env.bat"
call "C:\ProgramFolder\QGIS30402\bin\py3_env.bat"

@echo on
pyuic5 -o Sample_Menu_02_Base.py Sample_Menu_02_Base.ui


Sample_Menu_02_Base.ui


<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SampleMenu02Base</class>
<widget class="QWidget" name="SampleMenu02Base">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>336</width>
<height>152</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QPushButton" name="pushButton_go">
<property name="geometry">
<rect>
<x>90</x>
<y>90</y>
<width>101</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_cancel">
<property name="geometry">
<rect>
<x>210</x>
<y>90</y>
<width>101</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>キャンセル</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit">
<property name="geometry">
<rect>
<x>30</x>
<y>30</y>
<width>251</width>
<height>31</height>
</rect>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>


Sample_Menu_02_Base.py


# -*- coding: utf-8 -*-

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_SampleMenu02Base(object):
def setupUi(self, SampleMenu02Base):
SampleMenu02Base.setObjectName("SampleMenu02Base")
SampleMenu02Base.resize(336, 152)
self.pushButton_go = QtWidgets.QPushButton(SampleMenu02Base)
self.pushButton_go.setGeometry(QtCore.QRect(90, 90, 101, 41))
self.pushButton_go.setObjectName("pushButton_go")
self.pushButton_cancel = QtWidgets.QPushButton(SampleMenu02Base)
self.pushButton_cancel.setGeometry(QtCore.QRect(210, 90, 101, 41))
self.pushButton_cancel.setObjectName("pushButton_cancel")
self.lineEdit = QtWidgets.QLineEdit(SampleMenu02Base)
self.lineEdit.setGeometry(QtCore.QRect(30, 30, 251, 31))
self.lineEdit.setObjectName("lineEdit")

self.retranslateUi(SampleMenu02Base)
QtCore.QMetaObject.connectSlotsByName(SampleMenu02Base)

def retranslateUi(self, SampleMenu02Base):
_translate = QtCore.QCoreApplication.translate
SampleMenu02Base.setWindowTitle(_translate("SampleMenu02Base", "Form"))
self.pushButton_go.setText(_translate("SampleMenu02Base", "OK"))
self.pushButton_cancel.setText(_translate("SampleMenu02Base", "キャンセル"))


画像






③qrcファイルをpythonファイルに変換


「./_resouce/icon/resources.bat」を実行して、qrcファイルとアイコン画像をpythonファイルに変換します。


./_resouce/icon


resources.bat


@echo off
call "C:\ProgramFolder\QGIS30402\bin\o4w_env.bat"
call "C:\ProgramFolder\QGIS30402\bin\qt5_env.bat"
call "C:\ProgramFolder\QGIS30402\bin\py3_env.bat"

@echo on
pyrcc5 -o resources.py resources.qrc


resources.qrc

<RCC>
<qresource prefix="/plugins/Sample" >
<file>icon.png</file>
</qresource>
</RCC>


resources..py


# -*- coding: utf-8 -*-

from PyQt5 import QtCore

qt_resource_data = b"\
\x00\x00\x0c\xe3\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x19\x00\x00\x00\x19\x08\x06\x00\x00\x00\xc4\xe9\x85\x63\
\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\
\x00\x00\x00\x20\x63\x48\x52\x4d\x00\x00\x7a\x26\x00\x00\x80\x84\
\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00\x75\x30\x00\x00\xea\x60\
\x00\x00\x3a\x98\x00\x00\x17\x70\x9c\xba\x51\x3c\x00\x00\x00\x09\
\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\
\x18\x00\x00\x04\x83\x69\x54\x58\x74\x58\x4d\x4c\x3a\x63\x6f\x6d\
\x2e\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\x00\x00\x00\x3c\
\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\x78\x6d\x6c\x6e\x73\x3a\
\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\x73\x3a\x6d\x65\x74\x61\
\x2f\x22\x20\x78\x3a\x78\x6d\x70\x74\x6b\x3d\x22\x58\x4d\x50\x20\
\x43\x6f\x72\x65\x20\x35\x2e\x34\x2e\x30\x22\x3e\x0a\x20\x20\x20\
\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\x78\x6d\x6c\x6e\x73\x3a\x72\
\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\
\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\
\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\x44\x65\x73\
\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\x6f\
\x75\x74\x3d\x22\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x65\x78\x69\x66\x3d\x22\x68\x74\
\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\
\x6d\x2f\x65\x78\x69\x66\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\
\x20\x20\x20\x20\x20\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x74\
\x69\x66\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\
\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x74\x69\x66\x66\x2f\x31\x2e\
\x30\x2f\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x3d\x22\x68\x74\x74\x70\x3a\
\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\
\x61\x70\x2f\x31\x2e\x30\x2f\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\
\x20\x20\x20\x3c\x65\x78\x69\x66\x3a\x53\x63\x65\x6e\x65\x43\x61\
\x70\x74\x75\x72\x65\x54\x79\x70\x65\x3e\x30\x3c\x2f\x65\x78\x69\
\x66\x3a\x53\x63\x65\x6e\x65\x43\x61\x70\x74\x75\x72\x65\x54\x79\
\x70\x65\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x65\x78\
\x69\x66\x3a\x50\x69\x78\x65\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\
\x6f\x6e\x3e\x31\x31\x30\x38\x3c\x2f\x65\x78\x69\x66\x3a\x50\x69\
\x78\x65\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\x6f\x6e\x3e\x0a\x20\
\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x65\x78\x69\x66\x3a\x43\x6f\
\x6d\x70\x6f\x6e\x65\x6e\x74\x73\x43\x6f\x6e\x66\x69\x67\x75\x72\
\x61\x74\x69\x6f\x6e\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x20\x20\x20\x3c\x72\x64\x66\x3a\x53\x65\x71\x3e\x0a\x20\x20\x20\
\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x72\x64\x66\
\x3a\x6c\x69\x3e\x31\x3c\x2f\x72\x64\x66\x3a\x6c\x69\x3e\x0a\x20\
\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x72\
\x64\x66\x3a\x6c\x69\x3e\x32\x3c\x2f\x72\x64\x66\x3a\x6c\x69\x3e\
\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x3c\x72\x64\x66\x3a\x6c\x69\x3e\x33\x3c\x2f\x72\x64\x66\x3a\x6c\
\x69\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x20\x20\x3c\x72\x64\x66\x3a\x6c\x69\x3e\x30\x3c\x2f\x72\x64\x66\
\x3a\x6c\x69\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x20\x3c\x2f\x72\x64\x66\x3a\x53\x65\x71\x3e\x0a\x20\x20\x20\x20\
\x20\x20\x20\x20\x20\x3c\x2f\x65\x78\x69\x66\x3a\x43\x6f\x6d\x70\
\x6f\x6e\x65\x6e\x74\x73\x43\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\
\x69\x6f\x6e\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x65\
\x78\x69\x66\x3a\x43\x6f\x6c\x6f\x72\x53\x70\x61\x63\x65\x3e\x31\
\x3c\x2f\x65\x78\x69\x66\x3a\x43\x6f\x6c\x6f\x72\x53\x70\x61\x63\
\x65\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x65\x78\x69\
\x66\x3a\x50\x69\x78\x65\x6c\x58\x44\x69\x6d\x65\x6e\x73\x69\x6f\
\x6e\x3e\x31\x34\x37\x38\x3c\x2f\x65\x78\x69\x66\x3a\x50\x69\x78\
\x65\x6c\x58\x44\x69\x6d\x65\x6e\x73\x69\x6f\x6e\x3e\x0a\x20\x20\
\x20\x20\x20\x20\x20\x20\x20\x3c\x65\x78\x69\x66\x3a\x45\x78\x69\
\x66\x56\x65\x72\x73\x69\x6f\x6e\x3e\x30\x32\x32\x31\x3c\x2f\x65\
\x78\x69\x66\x3a\x45\x78\x69\x66\x56\x65\x72\x73\x69\x6f\x6e\x3e\
\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x65\x78\x69\x66\x3a\
\x46\x6c\x61\x73\x68\x50\x69\x78\x56\x65\x72\x73\x69\x6f\x6e\x3e\
\x30\x31\x30\x30\x3c\x2f\x65\x78\x69\x66\x3a\x46\x6c\x61\x73\x68\
\x50\x69\x78\x56\x65\x72\x73\x69\x6f\x6e\x3e\x0a\x20\x20\x20\x20\
\x20\x20\x20\x20\x20\x3c\x74\x69\x66\x66\x3a\x4f\x72\x69\x65\x6e\
\x74\x61\x74\x69\x6f\x6e\x3e\x31\x3c\x2f\x74\x69\x66\x66\x3a\x4f\
\x72\x69\x65\x6e\x74\x61\x74\x69\x6f\x6e\x3e\x0a\x20\x20\x20\x20\
\x20\x20\x20\x20\x20\x3c\x74\x69\x66\x66\x3a\x52\x65\x73\x6f\x6c\
\x75\x74\x69\x6f\x6e\x55\x6e\x69\x74\x3e\x32\x3c\x2f\x74\x69\x66\
\x66\x3a\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x55\x6e\x69\x74\
\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3c\x78\x6d\x70\x3a\
\x43\x72\x65\x61\x74\x6f\x72\x54\x6f\x6f\x6c\x3e\x49\x6e\x73\x74\
\x61\x67\x72\x61\x6d\x3c\x2f\x78\x6d\x70\x3a\x43\x72\x65\x61\x74\
\x6f\x72\x54\x6f\x6f\x6c\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\
\x72\x64\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\
\x0a\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x0a\x3c\
\x2f\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x3e\x0a\x15\x36\xfc\xc5\
\x00\x00\x07\xca\x49\x44\x41\x54\x48\x0d\x75\x56\x6b\x6c\x14\xd7\
\x19\x3d\xf7\xce\x9d\xd9\xf7\x7a\xbd\x6b\xef\x06\xdb\x80\x5d\x83\
\x41\xc6\x96\xa1\x55\x41\xa4\x90\x18\x45\xa5\x21\x28\x34\x50\x19\
\xa2\xd2\xaa\x21\xa4\xd0\xa7\x1a\xa9\x51\x4b\xaa\xaa\xb2\x50\x13\
\xd2\x56\x0d\xb4\x89\xa2\x46\x51\xd3\x12\x29\xa4\x82\x06\x24\x54\
\xea\x2a\x04\x61\x5a\x0a\x54\x02\x1c\x87\x87\x5b\x5e\x6b\xb0\x17\
\xef\xda\xc6\xf6\xee\xce\x3e\xe6\x79\xfb\x8d\x11\x51\x5b\xa9\xf3\
\x63\x66\xee\x68\xee\x3d\xf7\x3b\xe7\x7c\xdf\x77\x19\xfe\xe7\x3a\
\x78\xb0\x47\xd9\xbc\xf9\x90\xe3\x7d\x1e\x97\xf5\x61\xb7\xb4\x65\
\x83\xed\x4e\xaf\x93\xcc\xe8\x72\xa5\xd6\xa2\x28\x6a\xd8\xb1\xb9\
\x1e\xf6\xab\x69\x55\x51\x06\x25\x9c\x3e\x43\x11\x47\x93\xec\x0d\
\xdd\x9b\x23\x65\x8f\xc2\xd8\xfd\xf9\xde\xd8\xbb\xd8\xfd\xc7\xfd\
\xfb\x49\xd9\x2d\xd6\xb0\x7e\xdb\x1b\x1d\x38\xf3\xc5\x5d\xab\x3a\
\x12\xcf\x07\x43\xf9\x14\xe7\x33\x80\xbb\x08\xa6\xc5\x20\x5d\x0b\
\x7e\x01\x84\xd5\x00\x04\x7c\xf4\x67\x19\x79\x83\xe5\x38\x13\xfb\
\xa2\xbe\xbd\xaf\x78\x73\xa5\xec\x15\x8c\xf5\xce\xae\xe3\x8d\x3f\
\x01\x91\x04\xc0\x08\xe0\xd8\xd0\xc6\xb6\x68\xa0\xf4\xfe\x9c\xfa\
\xa6\x0e\xe1\xc6\x50\xa7\x3d\x6e\x17\x9d\x7f\xd1\xaf\x57\x98\xc2\
\x2a\x9c\xf3\x30\xd3\xb8\x2d\x05\x53\x5c\x29\x2d\xe9\x4a\x1b\x5c\
\x68\x22\x48\x2b\x15\x4d\x76\xb9\x60\x04\xbf\xd4\x14\x7d\xf5\xda\
\x7f\x02\xcd\x82\x3c\x00\xe8\x1f\x7e\x78\xa5\x1f\x75\xfd\x2e\x87\
\xd6\x54\x17\x35\xf3\xd3\x61\xe1\x8c\x3f\xcd\x3b\xda\x1b\xc1\x34\
\x1d\xa6\x33\x02\xcb\x3d\x0d\x47\x16\x68\x77\x11\x70\x94\xa0\x29\
\x41\x58\x4e\xc5\x55\x95\xa0\x3d\x56\x2a\x6b\x8e\x65\x9a\xad\x89\
\xe4\x1a\xc6\x5e\x3a\xf3\x00\x88\x3d\xe0\xf0\xe6\xc4\xc6\xb6\xb2\
\xe5\xbf\x64\xb9\xaa\xd6\x54\x1b\xb6\x34\xa1\xa9\xc5\x72\x08\x6f\
\xee\x8f\xa2\x39\x96\xc4\xc6\xc7\x97\x22\x9e\x6a\xa4\x88\x74\x38\
\x78\x0f\x86\x95\x87\xc2\x88\x32\xae\x10\x30\xd1\xc9\x04\x6c\xdb\
\xb1\xb8\xea\xa8\x8a\xac\x35\xa1\xa8\x9d\x7e\xf6\x23\x8a\xe8\xa0\
\xc2\x1f\x88\x24\x84\x72\xb8\x31\x09\x6d\x7e\x3c\x6a\xf9\x85\x5f\
\x55\x88\xf1\x86\x98\x82\x25\x8b\x43\x78\xbb\x7f\x12\x47\xfe\x32\
\x80\xcc\xed\xab\xa8\x96\x38\xa6\xef\xa6\x10\x50\xd5\x59\x00\x8f\
\x71\xc1\xe3\x24\x84\x80\xa6\x72\xd5\xb6\x2c\xcb\xa7\x48\x4d\x5a\
\x95\xc3\xb3\x7a\xb0\xcd\xce\x2c\x5d\x59\x7d\xc7\xae\x70\xc8\xd9\
\x53\xd0\xab\xa6\xc6\x7d\x9a\x2a\x1c\x84\xb5\x0e\x58\x46\x1d\xfe\
\xf0\xa1\x83\x81\x01\x03\xb4\x61\xd4\x12\xa8\x52\x34\xd0\xde\x32\
\x89\xa7\x7a\x18\x45\xc3\xa0\x28\x0a\x38\xe3\x44\xe5\x24\x1c\x37\
\x01\x4d\x04\x90\xb7\xb3\x66\x42\xf3\x6b\x0e\x62\x2f\xaa\xec\x85\
\x57\xd8\x95\x71\x84\x6b\xfd\x5f\xbf\xe1\x53\x83\xa9\x00\xf7\xb9\
\x36\xf2\xdc\x32\xc2\xa8\x16\xd7\x62\xf4\xb6\x8a\xbd\xef\x0c\x22\
\x10\xe7\x68\x0c\x49\x70\xbd\x84\xc3\x7b\x6e\xe0\xc8\x95\x45\x68\
\x6d\x57\x61\xd9\x65\x0a\x44\x85\x24\x87\x71\x8a\xdc\x41\x00\xa8\
\x46\xe0\x16\x63\x2e\xd7\x24\x37\xa7\xec\xdc\xc5\x0f\x0a\x0b\xd8\
\x48\x7e\xc7\x97\xe3\x51\xff\xbb\x56\xc5\x67\x0b\x45\x13\x8e\x23\
\x71\xfa\x64\x3b\x72\x23\x1c\xbb\xdf\xba\x89\xc9\x4c\x05\x7a\xa2\
\x82\xdd\x2b\x34\x3c\xb1\x3a\x8a\x9a\xd6\x08\x1a\x96\x2e\x86\x16\
\x08\xc1\x70\x4f\x50\x24\x92\x34\x91\x08\x2a\x75\xb0\x91\x83\x53\
\x71\xa0\x16\x53\x90\x61\xcb\x36\xb4\x7b\x22\x53\xc8\x6c\xe5\x2a\
\xc3\xba\x00\xf9\xdd\x91\x26\xb8\x6a\xe1\xd4\x5f\x43\x70\x8d\x28\
\x46\x32\x39\x0c\x5f\xd0\xd1\xd6\x42\x3c\x65\x35\x1c\x1f\x52\x31\
\xc9\xc3\x38\x72\xbc\x82\x0f\x8e\x8c\x41\xd8\xe3\xa4\x4b\x2d\xaa\
\x96\x40\x4e\x2f\xa0\xea\x94\x28\x3f\xc2\x80\x4f\xc0\x4a\x8e\x41\
\x09\xba\x88\xb0\x65\xf8\x94\x78\x64\x1d\x77\x5d\x5f\x57\xd1\xb6\
\xa0\xf2\x1a\x72\x3e\xb9\x47\xe9\xc0\x8f\x5f\xbb\x88\xf4\xb4\x8b\
\xdd\x7b\xdb\xe1\x12\x05\x5b\xbe\x50\x87\xbf\x5d\x50\xf0\xc3\xfd\
\x2e\xe2\x6d\x01\xac\x5a\x9f\x81\xab\x8d\xc1\xb4\x0d\x4a\xca\x20\
\xe6\x46\xe6\x91\x2e\x24\xaf\x74\xc0\x64\x84\x5c\xa6\xc2\xd4\xfd\
\xac\xaa\xa7\x51\x9a\xca\x77\x89\x8a\xa5\xb4\xa8\xa6\x40\xc8\x6f\
\xf3\x81\xc1\x1a\x44\x42\x49\xa4\x75\x89\xaf\x75\x35\x41\xd5\x38\
\xed\xd6\x45\xfb\x82\x20\x86\xce\x2d\x06\xf3\x3d\x84\xfa\xc6\x6b\
\xa8\xad\x29\x11\x80\xa7\x87\x0b\xc3\xa9\x40\x55\x54\x10\x6b\xb0\
\x5d\x41\xf4\xd9\xf0\x49\x17\x4a\x74\x8c\x67\x27\x6b\xf1\xcb\x9f\
\xe7\x5a\x94\xa7\x77\xce\x7b\xb9\xb6\x86\xcb\xab\x43\x61\xb6\xff\
\xf7\x41\xdc\xcb\x17\x90\xbb\x95\xc7\xa9\x0f\xef\xe2\xbd\xdf\x51\
\xf2\x51\xd8\xc2\xb1\x50\x13\x53\xf1\xd1\xa5\x2c\xec\x32\xc7\xbc\
\x66\x4a\x40\x37\x03\x85\x47\x48\x74\x41\x54\x51\xd9\x62\xe4\x40\
\xee\xc2\x74\xcb\x10\x42\xa2\x5a\xf6\xb1\x17\xbf\x55\x95\x05\x36\
\xe4\x63\x63\x85\xef\x16\xf5\x8a\x0c\xef\xfc\x66\x5c\xde\xb8\xaa\
\xb0\x3b\x33\x65\x74\x34\x09\xfa\xd1\x81\x50\x25\x85\x4e\xf3\x89\
\x8a\x81\x33\x26\xb6\x3d\x3b\x07\x5b\x37\x35\x63\x55\x77\x1b\x7c\
\xa1\x0a\xed\xfc\x2c\x69\x39\x83\x8a\x65\x13\xa0\x4a\x69\xe1\x9f\
\xb5\xb2\x4f\xf8\x91\x9d\xb6\xe4\x86\xcd\xc3\xec\xf5\x9f\xb6\xea\
\x9c\x9c\x91\x0e\x6a\x21\x04\xb9\xe3\x4a\x56\xc1\x67\x9a\x89\x5b\
\x32\xb2\x69\xd3\x6e\xaa\x12\x46\xc5\x40\x76\xc2\xc1\xc3\x6b\x23\
\xb8\x71\x73\x0a\xc5\xaa\x83\x13\xa7\xd2\xb8\x75\x43\x43\x29\xff\
\x39\xc0\x69\x45\x40\xd4\x10\x4d\x26\x45\x77\x87\xca\x0c\x15\x70\
\xd7\xc1\xfc\xe4\x42\xf7\xfd\xb7\x9e\xc2\xc4\xb5\x44\x9a\x17\xcb\
\xa5\x41\x4e\xc5\x34\x99\x90\x72\xe4\xba\x0d\xdb\xb1\x41\x68\xe4\
\x14\x72\x89\x29\xa1\x52\xa2\x7d\xfa\xb3\x09\xbc\xf9\x1b\x3f\x5e\
\x7e\x75\x3e\xfe\xf8\xe7\x31\xac\x5f\x7f\x1c\xdf\xfb\xfe\x31\x14\
\xa7\x0d\xdc\x4d\x37\xc3\xa9\x7e\x1e\x86\xde\x0d\xee\x76\xa2\x4a\
\x85\xcf\xe4\x1c\xe9\x3b\xa6\x3c\xfd\x8f\x3b\x68\x5a\x3e\x30\x28\
\x38\x8f\xf6\x71\x95\x7f\x85\xfb\x2b\xa4\x9c\x24\x8e\x3d\x00\x1b\
\xd9\x31\x07\xdd\x8f\x84\xe1\x0b\x36\x60\xd2\x8c\xe0\xed\x63\x61\
\x34\xd4\xd7\x63\xed\x7a\x05\xc3\x59\x07\x0b\x16\x09\x1c\x3c\x3a\
\x88\xf3\x67\x67\x10\xab\x0d\x62\x34\x23\xf1\xdc\x33\xcd\x58\xb9\
\x6a\x2e\xc2\x3e\x8e\xb1\xc9\x51\x5c\x9a\xfc\x18\xf6\x9d\x42\x9f\
\xf2\xe8\xb6\x79\xe9\x3a\x35\xb4\x7d\x3c\xc3\xa3\xc7\xfb\xaa\x6e\
\xaa\xc1\x65\x96\xe5\xd5\x25\x09\x53\x26\x50\x88\x35\x40\xce\x89\
\xe0\xd2\x04\xc7\x81\x73\xd3\x38\x33\x30\x41\x14\x05\x60\x46\x19\
\x76\x6e\x1b\xc1\xc2\x25\x79\x8c\xce\x14\x31\x3a\xa1\x63\xa6\x90\
\xc1\xe2\x94\x41\xdd\x6e\xc2\x4d\xb2\x98\xb2\x72\x59\x47\x2e\xd9\
\x72\xe4\xdb\x62\xf3\x92\x43\xfa\x88\xbe\x63\x5f\x5b\x7b\x74\x0f\
\x60\xd8\xb9\xf1\xa0\x96\xd7\xab\x98\xdb\x9c\x80\x2e\x52\x88\x7a\
\x14\x67\xcb\xa8\x27\x23\x34\x24\x24\xce\x65\xa8\x55\x25\x6d\xbc\
\xf4\x0d\x0b\x2d\x8d\x3e\xa4\x52\x64\xf1\xce\x10\x72\xf7\x4c\xc4\
\x63\x93\xb0\x59\x15\xc7\xfe\x24\xed\x65\x21\xa1\x95\x2f\xbb\xfb\
\x1e\xdd\x7e\x45\x9f\x2d\x90\x5e\xb5\x7c\xfd\xdd\xed\x97\x0f\x1d\
\xa8\x5b\xf2\x50\x92\xbc\xe0\x06\xd4\xb3\xd7\xe3\x48\x25\xfd\xb3\
\xb9\xc0\xc8\x08\xe7\xc7\x39\xb5\x43\x05\xbb\x7b\x4c\xf4\x3c\x31\
\x85\xd6\x06\x17\x65\xca\xaf\xa2\x51\x20\x9d\x5d\xaa\xf4\x16\xb9\
\xcc\xc1\xad\xac\x61\xf5\x9d\x76\xd5\x5f\xff\xca\xbc\x82\xab\xef\
\x74\x78\x6b\xf3\x1e\xea\xe9\xde\xcb\x77\xb6\xfe\x76\x53\xa9\x9a\
\x33\x85\x16\x51\xa7\x8b\x41\xab\x3e\x50\x85\x59\xc8\xe3\xee\x68\
\x01\xe7\xaf\x5b\x78\xe1\xc9\x02\x2e\xbe\x31\x8c\x1f\x3c\x77\x1b\
\x2d\x73\xa8\x0b\x56\x54\xca\x72\x9a\xca\xa9\xd4\x0b\x0d\x54\x8b\
\xe9\xd5\xb5\xf2\x53\x5c\xbd\x75\x95\x99\x1b\x3b\x7d\x9b\xbc\x75\
\xd1\x43\x3d\xdf\x7b\xf6\xf6\x76\x8b\xde\x5e\xaf\xb7\x3f\xb6\x92\
\xbc\xde\x8f\x78\x52\xdb\xba\xa5\xd3\xfc\xf8\x23\x47\x88\xa8\xc2\
\xb7\x6d\x88\x63\xc7\x8e\x56\x32\xc5\x3f\x31\x55\xba\x40\xd5\x61\
\x1e\xed\xde\x26\x27\xcd\x50\x0e\xa9\x94\x4b\x3e\x97\x73\xdb\x16\
\xa1\xaa\x36\x9c\x76\xcd\x15\x1b\x33\xdd\xb8\x74\xe8\x6c\x77\x6f\
\xaf\xe8\xef\xed\xb5\x89\x03\x0f\xc4\x03\xe8\xa6\xe3\xc1\x89\xb3\
\x5d\xcb\x65\xe7\xc2\x66\x76\x79\x78\x5c\xd1\xea\xe6\x2b\xfc\xb1\
\xd5\x9a\xfd\xf7\x5b\x15\x3b\x3b\x1e\x75\x0c\xbb\x41\x16\x74\x07\
\xa6\x59\xa4\xee\xce\x1c\x2a\x8e\xd4\xa3\x14\x5b\x23\x9f\x87\xc3\
\x3e\xed\xe6\xdd\xca\x65\x9f\x3f\xd9\xe9\x01\x9c\x3c\x79\x1f\xc0\
\x5b\xff\x13\x4d\xbc\x01\xba\x09\xa8\xdf\x03\x04\x16\xaf\x78\x66\
\x97\x2f\x14\x79\xde\x70\x02\xa9\x42\x55\x20\xde\x38\x82\xaf\x3e\
\xa9\x60\xf5\xf2\x5a\xc4\x13\x1a\x22\x51\x0b\xd1\x80\x40\xd9\xe0\
\x94\xb4\x95\x9c\x0a\xff\xbe\x86\xd8\xcf\x66\x4f\x2b\x1e\xc0\x9a\
\x35\xbd\xb3\xeb\x78\x6b\xfd\x37\x88\xf7\x05\x9e\x46\x0f\xce\x4d\
\x4b\xc2\x4d\x4b\x3b\x37\x68\x60\xeb\x2c\x83\x77\x8d\x0c\xb1\x96\
\xd5\xcf\xb2\xf0\x2f\x7e\xa2\xe9\x9a\xc2\xd3\xf1\x50\x60\x30\x15\
\xad\xe9\xf3\x2b\xca\x51\x3a\x02\xfd\xdf\x73\xd7\xbf\x01\x33\x86\
\xa2\x97\x55\xc3\x9d\xbf\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
\x60\x82\
"

qt_resource_name = b"\
\x00\x07\
\x07\x3b\xe0\xb3\
\x00\x70\
\x00\x6c\x00\x75\x00\x67\x00\x69\x00\x6e\x00\x73\
\x00\x06\
\x05\x98\x47\x25\
\x00\x53\
\x00\x61\x00\x6d\x00\x70\x00\x6c\x00\x65\
\x00\x08\
\x0a\x61\x5a\xa7\
\x00\x69\
\x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
"

qt_resource_struct_v1 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
\x00\x00\x00\x26\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
"

qt_resource_struct_v2 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x26\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x67\xcb\x77\x04\xdc\
"

qt_version = [int(v) for v in QtCore.qVersion().split('.')]
if qt_version < [5, 8, 0]:
rcc_version = 1
qt_resource_struct = qt_resource_struct_v1
else:
rcc_version = 2
qt_resource_struct = qt_resource_struct_v2

def qInitResources():
QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)

def qCleanupResources():
QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)

qInitResources()


画像






④QGISプラグインファイル一式を構築


各ファイルを構築して、QGISプラグインファイル一式を作成します。


./dist/Sample


metadata.txt


[general]
name=Sample
qgisMinimumVersion=3.0
description=QGIS Sample Plugin
version=1.0
author=Yasunori Kirimoto
email=contact@day-journal.com

about=QGIS Sample Plugin

tracker=https://github.com/dayjournal/qgis3plugin-starter/issues
repository=https://github.com/dayjournal/qgis3plugin-starter

tags=vector

homepage=
category=Vector
icon=icon.png

# experimental flag
experimental=False

# deprecated flag (applies to the whole plugin, not just a single version)
deprecated=False


init.py


# -*- coding: utf-8 -*-

def classFactory(iface):
from .Sample import Sample
return Sample(iface)


Sample.py


# -*- coding: utf-8 -*-

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from qgis.core import *
from qgis.gui import *
from .resources import *

#メニュー読み込み
from .Sample_Menu_01 import SampleMenu01
from .Sample_Menu_02 import SampleMenu02

import os
import os.path
import sys
import codecs

QString = str

try:
_fromUtf8 = QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s

class Sample:
def __init__(self, iface):
self.iface = iface
self.canvas = self.iface.mapCanvas()

self.plugin_dir = os.path.dirname(__file__)
locale = QSettings().value('locale/userLocale')[0:2]
locale_path = os.path.join(
self.plugin_dir,
'i18n',
'Sample_{}.qm'.format(locale))
if os.path.exists(locale_path):
self.translator = QTranslator()
self.translator.load(locale_path)
if qVersion() > '4.3.3':
QCoreApplication.installTranslator(self.translator)
self.actions = []
self.menu = u'Sample'
self.toolbar = self.iface.addToolBar(u'Sample')
self.toolbar.setObjectName(u'Sample')

def tr(self, message):
return QCoreApplication.translate('Sample', message)

def add_action(
self,
icon_path,
text,
callback,
enabled_flag=True,
add_to_menu=True,
add_to_toolbar=True,
status_tip=None,
whats_this=None,
parent=None):
icon = QIcon(icon_path)
action = QAction(icon, text, parent)
action.triggered.connect(callback)
action.setEnabled(enabled_flag)
if status_tip is not None:
action.setStatusTip(status_tip)
if whats_this is not None:
action.setWhatsThis(whats_this)
if add_to_toolbar:
self.toolbar.addAction(action)
if add_to_menu:
self.iface.addPluginToMenu(
self.menu,
action)
self.actions.append(action)
return action

def initGui(self):
self.win = self.iface.mainWindow()
icon_path = ':/plugins/Sample/icon.png'
#メニュー設定
self.add_action(
icon_path=None,
text=u"Menu01",
callback=self.Menu01,
parent=self.win)
self.add_action(
icon_path=None,
text=u"Menu02",
callback=self.Menu02,
parent=self.win)

def unload(self):
for action in self.actions:
self.iface.removePluginMenu(
u'Sample',
action)
self.iface.removeToolBarIcon(action)
del self.toolbar

#Menu01メニュークリック
def Menu01(self):
#SampleMenu01読み込み
self.sample_menu_01 = SampleMenu01(self.iface)
#Menu01クリックでメッセージ表示
self.sample_menu_01.message_add()

#Menu02メニュークリック
def Menu02(self):
#SampleMenu02読み込み
self.sample_menu_02 = SampleMenu02(self.iface)
#SampleMenu02Dialog表示
self.sample_menu_02.dlg.show()

def run(self):
pass


Sample_Menu_01.py


# -*- coding: utf-8 -*-

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from qgis.core import *
from qgis.gui import *

QString = str

try:
_fromUtf8 = QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s

class SampleMenu01:
def __init__(self, iface):
self.iface = iface
self.canvas = self.iface.mapCanvas()

def message_add(self):
#Menu01クリックでメッセージ表示
QMessageBox.information(None, u'ウィンドウ名', u'Menu01!!')


Sample_Menu_02_Dialog.py


# -*- coding: utf-8 -*-

from PyQt5 import uic, QtWidgets, QtCore

#Ui_SampleMenu02Base読み込み
from .Sample_Menu_02_Base import Ui_SampleMenu02Base

class SampleMenu02Dialog(QtWidgets.QDialog, Ui_SampleMenu02Base):
def __init__(self, parent=None):
super(SampleMenu02Dialog, self).__init__(parent)
self.setupUi(self)


Sample_Menu_02.py


# -*- coding: utf-8 -*-

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from qgis.core import *
from qgis.gui import *

#SampleMenu02Dialog読み込み
from .Sample_Menu_02_Dialog import SampleMenu02Dialog

QString = str

try:
_fromUtf8 = QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s

class SampleMenu02:
def __init__(self, iface):
self.iface = iface
self.canvas = self.iface.mapCanvas()
#SampleMenu02Dialog読み込み
self.dlg = SampleMenu02Dialog()
#ボタン設定
self.dlg.pushButton_go.clicked.connect(self.dlg_add)
self.dlg.pushButton_cancel.clicked.connect(self.dlg_cancel)

#キャンセルクリック
def dlg_cancel(self):
#SampleMenu02Dialog非表示
self.dlg.hide()

#OKクリック
def dlg_add(self):
#テキストボックス値取得
text_value = self.dlg.lineEdit.text()
#テキストボックス値をメッセージ表示
QMessageBox.information(None, u'ウィンドウ名', str(text_value))






⑤QGISで確認


プラグインが完成したところで、「Sample」ディレクトリを「C:\Users\ユーザー名\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins」にコピーします。

画像




QGISを起動するとプラグインを利用できます。

画像






PyQt5とQtDesignerを利用すると、QGIS3系プラグインを構築することが可能です!




QtとQGISについて、他にも記事を書いています。よろしければぜひ。
tags - Qt
tags - QGIS
Try #011 – QGIS3対応プラグインを登録公開してみた





book


Q&A