目次

3. リソースファイルとダイアログ画面を作る

3.1. pyrcc4コマンド

リソースを記述します。まだよくわかってないので、とりあえず、小メニューに表示するアイコンだけ定義してみました。

ファイル名は resource.qrc とします。

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

これは、main.py の:

self.action = QAction(QIcon(":/icon/marubatu32.png"), ・・・)

この部分に使われています。:

<qresource prefix="icon" >

で指定したprefixが、”/icon/” の部分に当たります。この部分はフォルダ名ではなく、prefix名です。


記述はしましたが、このままでは使えません。

Python形式に変換しないといけません。

・・・ここいらへんですよ。わたしがめっちゃハマったのは。(;´д`) まあ、厳密には、pyuic4の方なんですけど。 あれ消したり、これインストールしたり、環境がぐちゃぐちゃになってしまいました。 だから、わたしの環境で、今、やってる方法を書いておきますが、他の環境だったら違うかもー。

以下の通りにクリックすると、環境設定がすべて整ったDOS窓が開きます。:

「スタートボタン」→「すべてのプログラム」→「OSGeo4W」→「OSGeo4W Shell」

「OSGeo4W Shell」の正体は、

C:/OSGeo4W/OSGeo4W.bat

です。こんな一番わかりやすいとこにあるのに・・・後から考えると、本当に悔しいです。

@echo off
rem Root OSGEO4W home dir to the same directory this script exists in
set OSGEO4W_ROOT=%~dp0
rem Convert double backslashes to single
set OSGEO4W_ROOT=%OSGEO4W_ROOT:\\=\%
echo. & echo OSGEO4W home is %OSGEO4W_ROOT% & echo.

set PATH=%OSGEO4W_ROOT%\bin;%PATH%

rem Add application-specific environment settings
for %%f in ("%OSGEO4W_ROOT%\etc\ini\*.bat") do call "%%f"

rem List available o4w programs
rem but only if osgeo4w called without parameters
@echo on
@if [%1]==[] (cmd.exe /k o-help) else (cmd /c "%*")

そうそう。DOS窓開いて、この環境設定を全部自力でやろうとしてたんですよねー。アホですわ。( ;∀;)

それから、わたしの環境では、64bit版のShellを走らせると、 GDALのエントリポイントがみつからないというエラーが出るので使っていないのですが、 余計なことしなかったら、エラー出ないで使えるのかも?です。


話がそれたので戻します。

「OSGeo4W Shell」を起動し、resource.qrcがあるフォルダに移動して、:

pyrcc4 resource.qrc -o resource.py

と、実行してください。こんな感じ。

_images/sample2_1.jpg

これで、同じ場所に、resource.py が出来ました。

main.py で、最初に読み込もうとしてるのは、このファイルです。

3.2. Qt Creator

プラグインのボタンを押したら、1つの決まった処理しかできないようでは使い物になりません。

ずばり!大事なのはユーザーインターフェースでしょう! m9っ`Д´)

ってなわけで、ダイアログ画面を出せるようにしようと思います。

これがあれば、パラメータいれてもらえるし、処理も選んでもらえるもんね!


とりあえず、さっきプログラムで作った、ファイル選択の機能を、ダイアログ画面で行うようにしたいと思います。

Pythonで使う画面を作るのは、Qt Creatorってのを使うといいらしいです。

わたしは、Qtも初めてなので、簡単に使い方を書いておこうと思います。


Qt Creatorを起動します。

メニュー[ファイル]→[ファイル/プロジェクトの新規作成]を押して、新規作成画面を表示します

_images/sample2_2.jpg

ファイルとクラス/Qt → Qt Designer フォーム

_images/sample2_3.jpg

ダイアログを作りたいんで、Dialog・・・ボタンは自分で作るからいいや!で、 [Dialog without Buttons]を選択

次に進んで、フォルダ名やら名前やら入力して、バージョン管理もいらない~ と進んだら画面制作画面に遷ります。

因みにファイル名は、dialogUi.uiにしました。 デフォルトのdialog.ui にすると、こいつをPythonにコンバータしたとき dialog.pyになってしまい、プラグインの処理を書くファイルをdialog.pyにしたいわたしとしては不都合だからです。

_images/sample2_4.jpg

LabelとPushButtonとLineEditをドラッグ&ドロップで貼り付けて、プロパティを設定しました。

シグナル/スロットは作りません。

_images/sample2_5.jpg

メニュー[ファイル]→[保存] して、終了します。

3.3. pyuic4コマンド

Qt Creator で作ったファイルをPythonに変換します。

「OSGeo4W Shell」を起動し、dialogUi.uiがあるフォルダに移動して、:

pyuic4 dialogUi.ui -o dialogUi.py

これで、同じ場所に、dialogUi.py が出来ました。中身はこんなん。

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

# Form implementation generated from reading ui file 'dialogUi.ui'
#
# Created: Fri Jul 18 15:52:57 2014
#      by: PyQt4 UI code generator 4.10.2
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

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

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(402, 115)
        self.label = QtGui.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(20, 20, 131, 16))
        self.label.setObjectName(_fromUtf8("label"))
        self.shpFname_edt = QtGui.QLineEdit(Dialog)
        self.shpFname_edt.setGeometry(QtCore.QRect(20, 40, 331, 20))
        self.shpFname_edt.setObjectName(_fromUtf8("shpFname_edt"))
        self.shpFname_btn = QtGui.QPushButton(Dialog)
        self.shpFname_btn.setGeometry(QtCore.QRect(350, 40, 31, 23))
        self.shpFname_btn.setObjectName(_fromUtf8("shpFname_btn"))
        self.shpRead_btn = QtGui.QPushButton(Dialog)
        self.shpRead_btn.setGeometry(QtCore.QRect(300, 70, 75, 23))
        self.shpRead_btn.setObjectName(_fromUtf8("shpRead_btn"))

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

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
        self.label.setText(_translate("Dialog", "シェイプファイル名", None))
        self.shpFname_btn.setText(_translate("Dialog", "…", None))
        self.shpRead_btn.setText(_translate("Dialog", "読み込み", None))

これくらい簡単なものなら、慣れれば、Qt Creatorを使わないでも作れそうですね。

3.4. dialog.py

ダイアログ画面の処理を書きます

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

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from dialogUi import Ui_Dialog
from qgis.core import *
from qgis.gui import *

# ダイアログクラス
class Dialog(QDialog, Ui_Dialog):

  # 初期化
  def __init__(self, iface):
    QDialog.__init__(self)
    self.iface = iface

    # QT Designer で作った画面を設定
    self.ui = Ui_Dialog()
    self.ui.setupUi(self)

    # 「…」ボタンが押されたら、shpFname_btn()に飛ぶようセット
    QObject.connect(self.ui.shpFname_btn, SIGNAL("clicked()"), self.shpFname_btn)
    
    # 「読み込み」ボタンが押されたら、shpRead_btn()に飛ぶようセット
    QObject.connect(self.ui.shpRead_btn, SIGNAL("clicked()"), self.shpRead_btn)


  # 「…」ボタン押下
  def shpFname_btn(self):
    # ファイル選択ダイアログ
    self.fil = QFileDialog.getOpenFileName(None, "Open Shapefile", ".", "Shapefiles (*.shp)")
    self.filInfo = QFileInfo(self.fil)

    #ファイル名を表示
    self.ui.shpFname_edt.setText(self.filInfo.fileName())


  # 「読み込み」ボタン押下
  def shpRead_btn(self):
    # レイヤ追加
    self.iface.addVectorLayer(self.fil, self.filInfo.fileName(), "ogr")

3.5. main.pyを修正

main.pyを、ダイアログを呼ぶように修正します

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

from PyQt4.QtCore import *
from PyQt4.QtGui import *


# リソース読み込み
try:
  from . import resource
except ImportError:
  pass


# メインクラス
class main:

  # 初期化
  def __init__(self, iface):
    self.iface = iface

  # メニューセット
  def initGui(self):
    # 小メニューを作る
    self.action = QAction(QIcon(":/icon/marubatu32.png"), u"さんぷる1", self.iface.mainWindow())
    self.action.setObjectName("sample1")

    # 大メニューを作る
    self.menu = QMenu(self.iface.mainWindow())
    self.menu.setObjectName("daradara")
    self.menu.setTitle(u"だら$")
    self.menu.addAction(self.action)

    # 大メニューをメニューバーに挿入する
    menuBar = self.iface.mainWindow().menuBar()
    menuBar.insertMenu(self.iface.firstRightStandardMenu().menuAction(), self.menu)

    # 小メニューを押したとき実行するよう、トリガーをセット
    QObject.connect(self.action, SIGNAL("triggered()"), self.run)

  # 終了
  # (ここは、まだ未完成。ちゃんと消せてなくて、変な情報が残ってるみたい。わかったら修正する)
  def unload(self):
    #メニューを消す
    self.menu.deleteLater()

  # 実行
  def run(self):
    # ダイアログ読み込み
    from dialog import Dialog
    self.dlg = Dialog(self.iface)

    # 表示
    self.dlg.show()

    # 実行
    self.dlg.exec_()

3.6. 完成

メニュー[だら$]→[さんぷる1]

_images/sample2_6.jpg

[…]クリックでファイル選択ダイアログが開き、[読み込み]クリックでベクタレイヤに追加・表示します。

プラグイン置き場の中身はこんな感じになりました。Pythonって実行時にコンパイルしてるんですか?知りませんでした。

C:/Users/banjo/.qgis2/python/plugins/sample1

_images/sample2_7.jpg