Gọi các chức năng PyQGIS từ các biên tập viên bên ngoài (Linux)


8

Có thể tích hợp các trình soạn thảo Python bên ngoài (chẳng hạn như KDevelop) với QGIS, để có thể chạy các chức năng qgis.core, qgis.utilsv.v. bên ngoài Bảng điều khiển Python của QGIS không?

Theo hướng dẫn trên trang web của QGIS ( http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/intro.html ), tôi đã thử cách này, nhưng nó chỉ trả về 1 và không có gì khác:

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()

Nhu la:

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

Tôi đang chạy openSUSE Tumbleweed, 64-bit.

Câu trả lời:


8

Tôi sử dụng phần giới thiệu sau cho các ứng dụng độc lập:

# 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()

Khi ứng dụng không cần GUI (ví dụ: thực hiện một số công cụ địa lý), hãy thay thế dấu chấm lửng bằng một cái gì đó tương tự:

# 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()

Để làm việc với một hoặc nhiều lớp, bạn không phải thêm chúng vào bản đồ lớp đăng ký, chỉ cần tham chiếu chúng theo tên biến của chúng (ở đây layer1).

Khi bạn sử dụng GUI, ví dụ cửa sổ ánh xạ, đây sẽ là lớp python có nguồn gốc từ QMainWindow, thường được thiết kế với QtDesigner. Dấu chấm lửng phải được thay thế bằng mã như trong ví dụ tiếp theo:

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

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

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

Để kiểm tra phương pháp này mà không thực sự có GUI, hãy thử phiên bản giao diện điều chỉnh đã sửa đổi này:

# 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()

Nó gần giống như phiên bản console (vì thực tế không có đối tượng đồ họa), nhưng liên quan đến việc quit()dừng ứng dụng.

Để bắt đầu ứng dụng như vậy trên Linux:

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

Và trên máy 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

Một GUI rất cơ bản có thể trông như thế này:

# 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() 

Giao diện của nó sau khi nhấn nút Hình học :

bản giới thiệu

Bắt đầu với ví dụ đơn giản này, bạn có thể muốn triển khai tiện ích chú thích, hộp thoại thuộc tính, hộp thoại lớp, hành vi lựa chọn và chỉnh sửa, v.v.


Sử dụng mã của bạn như hiện tại, nó không bị sập nữa, nhưng nó dẫn đến kịch bản chỉ đơn giản là không hoạt động ở đó mãi mãi. Nó thậm chí không thể dừng lại bằng cách gửi SIGINT, nó phải được dừng lại với SIGKILL. Tôi vẫn còn thiếu một cái gì đó?
GreatEmerald

Bạn có thể chạy một ứng dụng độc lập VỚI hoặc KHÔNG CÓ GUI. Khi bạn có GUI, thì GUI sẽ điều khiển cho đến khi nó kết thúc bằng một thoát (). Việc khởi tạo lớp GUI như vậy sẽ thay thế mã cụ thể #app trong ví dụ của tôi. Nếu bạn không có GUI thì bạn không thể sử dụng các phương thức liên quan đến GUI, như activeLayer (). Tôi chỉnh sửa câu trả lời của tôi để bao gồm một ví dụ.
Detlev

Tôi đã thử điều đó (sao chép phần đầu tiên và chèn khối GUI thay vì eliipsis) và nhận được lỗi này: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 () chỉ là một ví dụ. Nếu bạn đã xây dựng GUI bằng QtDesigner hoặc từ đầu thì thay vào đó hãy chèn tên lớp này. Vì tôi không biết môi trường ứng dụng chính xác của bạn, tôi đã chỉ ra các nguyên tắc
Detlev

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.