dayjournal memo

Total 974 articles!!

Try #022 – PyQt5とQtDesignerを利用したQGIS3系プラグインの構築方法を紹介してみる

Yasunori Kirimoto's avatar

画像



画像




画像




この記事は、「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