外部エディターからのPyQGIS関数の呼び出し(Linux)


8

関数を実行することが可能であろうように、QGISで(例えばKDevelopのような)外部のPythonエディタを統合することが可能であるqgis.coreqgis.utilsなどQGIS Pythonコンソールの外側を?

QGIS Webサイト(http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/intro.html)のガイドラインに従って、これを試しましたが、1だけが返され、それ以外は何も返されません。

import sys
sys.path.append('/usr/share/qgis/python')
import qgis.core
import qgis.utils

app = qgis.core.QgsApplication([], True)
qgis.core.QgsApplication.initQgis()
qgis.utils.iface.addVectorLayer("testing.shp", "anewlayer", "ogr") 
aLayer = qgis.utils.iface.activeLayer()
print aLayer.name()

といった:

$ LD_LIBRARY_PATH=/usr/lib64/qgis/ python qgis-test.py && echo "OK" || echo "Died"
Died

私は64ビットのopenSUSE Tumbleweedを実行しています。

回答:


8

スタンドアロンアプリケーションには次のイントロを使用します。

# the_app.py
import os
import sys

from qgis.core import *
from PyQt4.QtGui import *     

def main():
    QgsApplication.setPrefixPath(os.environ['QGIS_PREFIX'], True)
    QgsApplication.initQgis()

    # app specific code
    ...

    QgsApplication.exitQgis()
    sys.exit(result)

if __name__ == '__main__':
    main()

アプリがGUIを必要としない場合(たとえば、ジオプロセシングを行う)、省略記号を次のようなものに置き換えます。

# app specific code (console)
print 'starting test'
layer1 = QgsVectorLayer('LineString', 'anewlayer', 'memory')
print layer.isValid()
QgsMapLayerRegistry.instance().addMapLayer(layer1, False)
print 'layer added to map layer registry'
aLayer = QgsMapLayerRegistry.instance().mapLayersByName('anewlayer')[0]
print aLayer.name()

1つ以上のレイヤーを操作するには、それらをマップレイヤーレジストリに追加する必要はありませんlayer1。それらを変数名(ここでは)で参照するだけです。

マッパーウィンドウなどのGUIを使用する場合、これはQMainDesignerで通常設計されるQMainWindowから派生したpythonクラスになります。次の例のように、省略記号をコードに置き換える必要があります。

# app specific code (GUI)
app = QApplication(sys.argv)

# create gui window
window = Main()
window.show() 

result = app.exec_()
app.deleteLater()

実際にGUIを使用せずにこのアプローチをテストするには、次の変更されたコンソールバージョンを試してください。

# app specific code (GUI ready)
app = QApplication(sys.argv)

layer1 = QgsVectorLayer('LineString', 'anewlayer', 'memory')
QgsMapLayerRegistry.instance().addMapLayer(layer1, False)
aLayer = QgsMapLayerRegistry.instance().mapLayersByName('anewlayer')[0]
print aLayer.name()

app.qApp.quit()

result = app.exec_()
app.deleteLater()

これはコンソールバージョンとほとんど同じですが(実際にはグラフィカルオブジェクトはありません)、quit()アプリケーションを停止するものに注意してください。

Linuxでそのようなアプリを起動するには:

#!/bin/sh
export PYTHONPATH="/usr/share/qgis/python"
export LD_LIBRARY_PATH="/usr/lib64/qgis"
export QGIS_PREFIX="/usr"
python the_app.py

そしてWindowsマシンでは:

SET OSGEO4W_ROOT=D:\OSGeo4W64
SET QGISNAME=qgis
SET QGIS=%OSGEO4W_ROOT%\apps\%QGISNAME%
SET QGIS_PREFIX=%QGIS%

CALL %OSGEO4W_ROOT%\bin\o4w_env.bat

SET PATH=%PATH%;%QGIS%\bin
SET PYTHONPATH=%QGIS%\python;%PYTHONPATH%

python the_app.py

非常に基本的なGUIは次のようになります。

# hand-made window with simple toolbar
class Ui_DemoWindow(object):
    def setupUi(self, window):
        window.setWindowTitle('Demo')

        self.centralWidget = QWidget(window)
        self.centralWidget.setFixedSize(640, 480)
        window.setCentralWidget(self.centralWidget)
        window.move(0, 0)

        self.layout = QVBoxLayout()    
        self.layout.setContentsMargins(0, 0, 0, 0)    
        self.centralWidget.setLayout(self.layout)

        self.toolBar = QToolBar(window)
        window.addToolBar(Qt.TopToolBarArea, self.toolBar)

        # quit action
        self.actionQuit = QAction('Quit', window)
        self.actionQuit.setShortcut(QKeySequence.Quit)

        # do something, here call function to create some geometries
        self.actionCreateGeom = QAction('Geometry', window)

        # link action to GUI elements
        self.toolBar.addAction(self.actionQuit)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.actionCreateGeom)


class Main(QMainWindow, Ui_DemoWindow):

    def __init__(self):    
        QMainWindow.__init__(self)
        self.setupUi(self)

        self.canvas = QgsMapCanvas()
        self.layout.addWidget(self.canvas)

        self.connect(self.actionQuit, SIGNAL('triggered()'), self.quit) 
        self.connect(self.actionCreateGeom, SIGNAL('triggered()'), self.some_geoms) 

    # quick and dirty: create layer with some features, add layer
    # to map canvas, and zoom canvas to full view
    def some_geoms(self):
        layer = QgsVectorLayer('LineString', 'anewlayer', 'memory')
        # add some features
        prov = layer.dataProvider()
        feats = []
        feat = QgsFeature()
        feat.setGeometry(QgsGeometry().fromPolyline([QgsPoint(-1,1), QgsPoint(1, -1)]))
        feats.append(feat)
        prov.addFeatures(feats)
        layer.updateExtents()

        QgsMapLayerRegistry.instance().addMapLayer(layer)
        self.canvas.setLayerSet([QgsMapCanvasLayer(layer)])
        self.canvas.zoomToFullExtent()    

    def quit(self):
        qApp.quit() 

ボタンジオメトリを押した後の様子:

デモ

この簡単な例から始めて、凡例ウィジェット、プロパティダイアログ、レイヤーダイアログ、選択と編集の動作などを実装することができます。


コードをそのまま使用すると、クラッシュすることはありませんが、スクリプトが永久にアイドル状態になるだけです。SIGINTを送信しても停止できません。SIGKILLで停止する必要があります。まだ何か不足していますか?
GreatEmerald

GUIなしまたはなしでスタンドアロンアプリを実行できます。GUIがある場合、GUIはquit()で終了するまでコントロールを取得します。このようなGUIクラスの初期化は、私の例の#app固有のコードを置き換えます。GUIがない場合、activeLayer()などのGUI関連のメソッドを使用できません。回答を編集して例を含めます。
Detlev 2016年

私はそれを試し(最初の部分をコピーして貼り付け、省略の代わりにGUIブロックを挿入しました)、次のエラーが発生しました:Traceback (most recent call last): File "test.py", line 25, in <module> main() File "test.py", line 15, in main window = Main() NameError: global name 'Main' is not defined
GreatEmerald

@GreatEmerald Main()は単なる例です。QtDesignerを使用して、または最初からGUIを作成した場合は、代わりにこのクラス名を挿入してください。私はあなたの正確なアプリ環境を知らないので、私は原則を示しました
Detlev

1
@wondimを見ていてくださいgis.stackexchange.com/questions/40375/...を
Detlev
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.