làm thế nào để tải openlayftimeplplin của QGIS trong tập lệnh python độc lập (không phải bảng điều khiển python nhúng QGIS)


9

nếu tôi cố tải plugin openlayers trong một ứng dụng độc lập thì nó luôn bị lỗi với Sai, mặc dù các đường dẫn được đặt và các plugin hiển thị.

(đã thử nghiệm trên Ubuntu 14.04, QGIS 2.4, python-2.7)

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os

import qgis
import qgis.gui, qgis.utils
from qgis.core import *
from PyQt4 import QtGui


# open an app
app = QtGui.QApplication(sys.argv)
# supply path to where is your qgis installed
QgsApplication.setPrefixPath(u'/usr', True)
# load providers
QgsApplication.initQgis()

# set up the plugins
qgis.utils.plugin_paths = \
    ['/usr/share/qgis/python/plugins',
    os.path.expanduser('~/.qgis2/python/plugins'),]
qgis.utils.updateAvailablePlugins()
print qgis.utils.available_plugins
print "...load:", qgis.utils.loadPlugin(u'openlayers_plugin')
print "...start:", qgis.utils.startPlugin(u'openlayers_plugin')
print "active:\n",qgis.utils.active_plugins

canvas = qgis.gui.QgsMapCanvas()
canvas.show()

Vấn đề ở đây là gì ? bài đăng Làm thế nào để tìm nạp các lớp openlayers từ pyqgis? đề cập đến giao diện điều khiển python nhúng, nơi plugin đã có sẵn một cách kỳ diệu trước đó.

cảm ơn!


Tại sao bạn cần plugin lớp mở bên ngoài trong một tập lệnh?
Nathan W

Một giải pháp khác cho vấn đề này đã được đăng ở đây
Henhuy

Câu trả lời:


3

Điều này là không bao giờ, cũng có thể với một số hack, sẽ hoạt động tốt. Các plugin thường sử dụng QgisInterfaceđối tượng cho phép truy cập vào giao diện và phương thức của QGIS. Bạn không có đối tượng này trong tập lệnh độc lập của bạn. Hầu hết các plugin, nếu không phải tất cả, không được thiết kế để chạy bên ngoài QGIS như thế này.


2
Điều này rất quan trọng để biết, tuy nhiên đáng tiếc. Là một người mới bắt đầu có kinh nghiệm ở QGis, tôi nghĩ thật tuyệt khi có thể phát triển các bước xử lý dữ liệu nhất định với tất cả các công cụ của QGis trong môi trường GUI đầy đủ, trong khi sau đó có thể có một tập lệnh công việc bị loại bỏ phiên bản. Một cái gì đó giống như DummyQgisInterfacelà có thể ...
qbit 22/215

7

Rất quan tâm đến mô hình TDD, tôi đã dành một chút thời gian để kết hợp một giao diện giả (dựa trên một số đoạn mã tôi tìm thấy trên internet) cho phép gọi các plugin bổ trợ của QGIS và QGIS.

Giao diện tôi đã xuất hiện với giao diện như sau và tôi đã sử dụng nó cho tất cả các bài kiểm tra đơn vị của mình kể từ:

# coding=utf-8
"""QGIS plugin implementation.

.. note:: This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.

.. note:: The basis of this source code was copied from the 'postgis viewer' application
     with original authors:
     Copyright (c) 2010 by Ivan Mincik, ivan.mincik@gista.sk
     Copyright (c) 2011 German Carrillo, geotux_tuxman@linuxmail.org
     Copyright (c) 2014 Tim Sutton, tim@linfiniti.com

"""
from qgis._core import QgsVectorLayer
from PyQt4.QtCore import QObject, pyqtSlot, pyqtSignal, QCoreApplication, QSize
from PyQt4.QtGui import QWidget
from qgis.core import QgsMapLayerRegistry, QgsApplication, QgsVectorLayer
from qgis.gui import QgsMapCanvasLayer, QgsMapCanvas

import logging
import sys

from mole import config

LOGGER = logging.getLogger('QGIS')


def set_up_interface():
    """
    Sets up a QGIS pseudo-application which enables calling methods as if when calling them from QGIS-console.

    :return qgis_app: Pseudo QGIS-instance
    :rtype: QgsApplication
    :return canvas: The map canvas
    :rtype: QgsMapCanvas
    :return iface: A dummy interface, giving access to needed method-calls
    :rtype: QgisInterface
    """
    gui_flag = True  # All test will run qgis in gui mode
    qgis_app = QgsApplication(sys.argv, gui_flag)
    prefix_path = config.qgis_prefix_path()
    qgis_app.setPrefixPath(prefix_path, True)
    qgis_app.initQgis()
    QCoreApplication.setOrganizationName('QGIS')
    QCoreApplication.setApplicationName('QGIS2')

    # parent = QWidget()
    # canvas = QgsMapCanvas(parent)
    # canvas.resize(QSize(400, 400))
    canvas = MyMapCanvas()

    iface = QgisInterface(canvas)

    return qgis_app, canvas, iface

#noinspection PyMethodMayBeStatic,PyPep8Naming
class QgisInterface(QObject):
    """Class to expose QGIS objects and functions to plugins.

    This class is here for enabling us to run unit tests only,
    so most methods are simply stubs.
    """
    currentLayerChanged = pyqtSignal(QgsMapCanvasLayer)

    def __init__(self, canvas):
        """Constructor
        :param canvas:
        """
        QObject.__init__(self)
        self.canvas = canvas
        self.legend_interface = MyLegendInterface()
        self.active_layer = None
        # Set up slots so we can mimic the behaviour of QGIS when layers
        # are added.
        LOGGER.debug('Initialising canvas...')
        # noinspection PyArgumentList
        QgsMapLayerRegistry.instance().layersAdded.connect(self.addLayer)
        # noinspection PyArgumentList
        QgsMapLayerRegistry.instance().layerWasAdded.connect(self.addLayer)
        # noinspection PyArgumentList
        QgsMapLayerRegistry.instance().removeAll.connect(self.removeAllLayers)

        # For processing module
        self.destCrs = None


    @pyqtSlot('QgsMapLayer')
    def addLayer(self, layer):
        """Handle a layer being added to the registry so it shows up in canvas.

        :param layer: list<QgsMapLayer> list of map layers that were added

        .. note: The QgsInterface api does not include this method, it is added
                 here as a helper to facilitate testing.

        .. note: The addLayer method was deprecated in QGIS 1.8 so you should
                 not need this method much.
        """
        # set the recently added layer as active
        # LOGGER.debug('Layer Count Before: %s' % len(self.canvas.layers()))
        current_layers = self.canvas.layers()
        final_layers = [] + current_layers
        final_layers.append(QgsMapCanvasLayer(layer))
        self.canvas.setLayerSet(final_layers)
        self.active_layer = layer

    @pyqtSlot()
    def removeAllLayers(self):
        """Remove layers from the canvas before they get deleted."""
        self.canvas.setLayerSet([])

    def newProject(self):
        """Create new project."""
        # noinspection PyArgumentList
        QgsMapLayerRegistry.instance().removeAllMapLayers()

    def legendInterface(self):
        """Get the legend."""
        return self.legend_interface

    def activeLayer(self):
        """Get pointer to the active layer (layer selected in the legend)."""
        return self.active_layer

    def setActiveLayer(self, layer):
        """Set the given layer as active.
        :param layer: Layer that shall be set active
        :type layer: QgsMapLayer
        """
        self.active_layer = layer

    class actionAddFeature(object):

        def __init__(self):
            pass

        def trigger(self):
            pass

    class actionZoomToLayer(object):

        def __init__(self):
            pass

        def trigger(self):
            pass

    # ---------------- API Mock for QgsInterface follows -------------------
    def zoomFull(self):
        """Zoom to the map full extent."""
        pass

    def zoomToPrevious(self):
        """Zoom to previous view extent."""
        pass

    def zoomToNext(self):
        """Zoom to next view extent."""
        pass

    def zoomToActiveLayer(self):
        """Zoom to extent of active layer."""
        pass

    def addVectorLayer(self, path, base_name, provider_key):
        """Add a vector layer.

        :param path: Path to layer.
        :type path: str

        :param base_name: Base name for layer.
        :type base_name: str

        :param provider_key: Provider key e.g. 'ogr'
        :type provider_key: str
        """
        pass

    def addRasterLayer(self, path, base_name):
        """Add a raster layer given a raster layer file name

        :param path: Path to layer.
        :type path: str

        :param base_name: Base name for layer.
        :type base_name: str
        """
        pass

    def addToolBarIcon(self, action):
        """Add an icon to the plugins toolbar.

        :param action: Action to add to the toolbar.
        :type action: QAction
        """
        pass

    def removeToolBarIcon(self, action):
        """Remove an action (icon) from the plugin toolbar.

        :param action: Action to add to the toolbar.
        :type action: QAction
        """
        pass

    def addToolBar(self, name):
        """Add toolbar with specified name.

        :param name: Name for the toolbar.
        :type name: str
        """
        pass

    def mapCanvas(self):
        """Return a pointer to the map canvas."""
        return self.canvas

    def mainWindow(self):
        """Return a pointer to the main window.

        In case of QGIS it returns an instance of QgisApp.
        """
        pass

    def addDockWidget(self, area, dock_widget):
        """Add a dock widget to the main window.

        :param area: Where in the ui the dock should be placed.
        :type area:

        :param dock_widget: A dock widget to add to the UI.
        :type dock_widget: QDockWidget
        """
        pass


class MyLegendInterface(object):

    def __init__(self):
        self.layer_visibility = {}

    def setLayerVisible(self, layer, yes_no):
        self.layer_visibility[layer.name()] = yes_no

    def isLayerVisible(self, layer):
        try:
            return self.layer_visibility[layer.name()]
        except KeyError:
            print('Layer {} has not been set (in)visible yet.'.format(layer.name()))
            return False


class MyMapCanvas(object):

    def __init__(self):
        self.layer_set = []

    def layers(self):
        return self.layer_set

    def layer(self, index):
        layer = self.layer_set[index].layer()
        return layer

    def setLayerSet(self, layer_set):
        self.layer_set = layer_set

    def layerCount(self):
        return len(self.layer_set)

Nếu bạn muốn kiểm tra / sử dụng QGIS cộng với sự tương tác với một plugin đã cài đặt ngay bây giờ, hãy làm như sau (trong setUp không đáng tin cậy của bạn, vd):

qgis_app, canvas, iface = set_up_interface()
plugin_name = 'openlayers_plugin'
utils.plugin_paths = [os.path.expanduser('~/.qgis2/python/plugins')]
utils.updateAvailablePlugins()
utils.loadPlugin(plugin_name)
utils.iface = self.iface
utils.startPlugin(plugin_name) 

Để biết thêm một số ví dụ sử dụng và một số ví dụ thực tế trên các ứng dụng QGIS thử nghiệm đơn vị, bạn có thể xem trang github của chúng tôi ( https://github.com/UdK-VPT/Open_eQuarter/tree/master/mole ). Các bài kiểm tra thư mục chứa tất cả các bài kiểm tra đơn vị (phần lớn là kiểm tra các mô-đun trong gói qgisinteraction, có chứa một mô-đun, tương tác với plugin point_sampling_tool-plugin).


Tôi nghĩ rằng tôi đã làm việc này nhưng phải thực hiện utils.iface = ifacehai dòng trước đó và phải chế nhạo một QssMessageBar trong iface ...
Spacesman
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.