Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Printemps des cartes 2024

#1 Sat 14 March 2015 20:52

Spynz
Juste Inscrit !
Date d'inscription: 14 Mar 2015
Messages: 6

QGIS : Creation de Plugin ?

Bonjour,
Je suis élève en Ecole d'ingénieur et j'ai un projet à réaliser sous QGIS. Je dois créer un plugin qui me permettra de faire des requêtes sur des arrêts et lignes de bus (par exemple la charge moyenne à telle heure de la journée de tel arrêt de telle ligne).

J'ai d'abord créé une base de données sous PostGreSQL, qui contient toutes mes données de charge (nombre de personnes dans un bus par rapport à sa capacité d'accueil) à des horaires différents des arrêts d'une ligne donnée.

Puis, j'ai créé avec "Plugin Builder" un plugin, et je l'ai personnalisé grâce à PyQt (pour avoir une interface avec le choix de la ligne, de l'arrêt, de l'heure ...). C'est ici que se pose mon problème.
En effet, je ne vois pas trop comment écrire mon plugin en python pour qu'il aille chercher mes layers dans QGIS et faire les requêtes dont j'ai besoin, et je n'ai pas trouvé de turoriels très clairs sur internet (Si vous en avez sous la main je suis très preneur big_smile). De plus, à chaque fois que je modifie la moindre ligne dans mon plugin, j'ai le message d'erreur suivant qui s'affiche dans QGIS :


Couldn't load plugin Class_remi due an error when calling its classFactory() method

Traceback (most recent call last):
  File "C:/PROGRA~1/QGISBR~1/apps/qgis/./pythonqgisutils.py", line 208, in startPlugin
    plugins[packageName] = package.classFactory(iface)
  File "C:/Users/guyon_000/.qgis2/python/pluginsClass_remi__init__.py", line 34, in classFactory
    from .Module_name_remi import Class_remi
  File "C:/PROGRA~1/QGISBR~1/apps/qgis/./pythonqgisutils.py", line 460, in _import
    mod = _builtin_import(name, globals, locals, fromlist, level)
  File "C:/Users/guyon_000/.qgis2/python/pluginsClass_remiModule_name_remi.py", line 26, in
    import resources
  File "C:/PROGRA~1/QGISBR~1/apps/qgis/./pythonqgisutils.py", line 460, in _import
    mod = _builtin_import(name, globals, locals, fromlist, level)
ImportError: No module named resources

Python version:
2.7.5 (default, May 15 2013, 22:44:16) [MSC v.1500 64 bit (AMD64)]

QGIS version:
2.6.1-Brighton Brighton, e2a51df

Python path: ['C:/PROGRA~1/QGISBR~1/apps/qgis/./python/plugins\processing', 'C:/PROGRA~1/QGISBR~1/apps/qgis/./python', u'C:/Users/guyon_000/.qgis2/python', u'C:/Users/guyon_000/.qgis2/python/plugins', 'C:/PROGRA~1/QGISBR~1/apps/qgis/./python/plugins', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\matplotlib-1.3.1-py2.7-win-amd64.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\nose-1.3.3-py2.7.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\tornado-4.0.1-py2.7-win-amd64.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\backports.ssl_match_hostname-3.4.0.2-py2.7.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\certifi-14.05.14-py2.7.egg', 'c:\osgeo4~1\apps\python27\lib\site-packages\python_dateutil-2.1-py2.7.egg', 'c:\osgeo4~1\apps\python27\lib\site-packages\six-1.3.0-py2.7.egg', 'C:\PROGRA~1\QGISBR~1\bin\python27.zip', 'C:\PROGRA~1\QGISBR~1\apps\Python27\DLLs', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\plat-win', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\lib-tk', 'C:\PROGRA~1\QGISBR~1\bin', 'C:\PROGRA~1\QGISBR~1\apps\Python27', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\PIL', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\jinja2-2.7.2-py2.7.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\markupsafe-0.23-py2.7-win-amd64.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\pytz-2012j-py2.7.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\win32', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\win32\lib', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\Pythonwin', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\Shapely-1.2.18-py2.7-win-amd64.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\six-1.3.0-py2.7.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\wx-2.8-msw-unicode', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\xlrd-0.9.2-py2.7.egg', 'C:\PROGRA~1\QGISBR~1\apps\Python27\lib\site-packages\xlwt-0.7.5-py2.7.egg', 'C:\Users\guyon_000\.qgis2\python\plugins\MetaSearch\ext-libs', 'C:\Users\guyon_000\.qgis2\python\plugins\mmqgis/forms', 'C:\PROGRA~1\QGISBR~1\apps\qgis\python\plugins\fTools\tools', 'C:/Users/guyon_000/Desktop/COURS ECN/EI2/Projet']


Merci d'avance pour votre aide!!

Hors ligne

 

#2 Sun 15 March 2015 16:08

SANTANNA
Moderateur
Lieu: Angers
Date d'inscription: 18 Jan 2008
Messages: 3799

Re: QGIS : Creation de Plugin ?

Bonjour,
La raison de cette erreur se trouve formulée ici

Code:

ImportError: No module named resources

Avez-vous pensé à générer le fichier python resources (à l'aide de  pyrcc4) comme statué dans le 1/ du fichier Readme du plugin?

Pour ce qui est du développement de l'extension, certains vous diront qu'il vaut mieux se lancer dans une simple écriture de script avant de vouloir en faire un plugin avec interface graphique. Mais quoi qu'il en soit, plusieurs pistes pour avancer:
- la doc de l'API : http://qgis.org/api/2.8/
- le livre de recettes : http://docs.qgis.org/2.6/fr/docs/pyqgis … index.html
- les plugins : installer des plugins proches de ce que vous voulez faire, en décortiquer le contenu et s'en inspirer pour créer le sien
- les moteurs de recherche (ici ou généraux)

EDIT : une autre piste à ne pas négliger tant pour avoir les fonctions que pour déboguer est la Console Python de QGIS. Très pratique.

Dernière modification par SANTANNA (Sun 22 March 2015 19:20)

Hors ligne

 

#3 Mon 16 March 2015 14:49

Spynz
Juste Inscrit !
Date d'inscription: 14 Mar 2015
Messages: 6

Re: QGIS : Creation de Plugin ?

Bonjour,
Merci beaucoup pour votre réponse, je vais essayer de continuer mon code grâce à ces documents.

Avez-vous pensé à générer le fichier python resources (à l'aide de  pyrcc4) comme statué dans le 1/ du fichier Readme du plugin?


Je n'arrive pas à effectuer la compilation du fichier resources, mais je pense avoir mal compris la méthode : j'ai ouvert une commande windows dans le dossier où se trouve mon plugin, et j'ai écrit: pyrcc4 -o resources.py resources.qrc
En faisant cela, la commande m'indique que "pyrcc4" n'est pas connu, ce qui ne m'étonne pas.

D'autre part, grâce aux documents, j'ai essayé de commencer à coder mon plugin, et une première erreur que je n'arrive pas à expliquer apparaît :

TypeError: QDialog(QWidget parent=None, Qt.WindowFlags flags=0): argument 1 has unexpected type 'QgisInterface'


Voici mon code:

Code:

# To change this license header, choose License Headers in Project Properties.
# To change this template file, choose Tools | Templates
# and open the template in the editor.

__author__ = "guyon_000"
__date__ = "$16 mars 2015 15:18:04$"

# -*- coding: utf-8 -*-
"""
/***************************************************************************
 Class_remi
                                 A QGIS plugin
 Description_remi
                              -------------------
        begin                : 2015-03-05
        git sha              : $Format:%H$
        copyright            : (C) 2015 by author_remi
        email                : igor.belot@orange.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""
# Import the PyQt and QGIS libraries
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
from qgis.utils import *
# Initialize Qt resources from file resources.py
import resources_rc
# Import the code for the dialog
from Module_name_remi_dialog import Class_remiDialog
import os.path


class Class_remi:
    """QGIS Plugin Implementation."""

    def __init__(self, iface):
        """Constructor.

        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        """
        # Save reference to the QGIS interface
        self.iface = iface
        # initialize plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # initialize locale
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(self.plugin_dir,'i18n','Class_remi_{}.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)

        # Create the dialog (after translation) and keep reference
        self.dlg = Class_remiDialog(self.iface)

    def initGui(self):
        
        # Create action that will start plugin configuration
        self.action = QAction(QIcon(":/plugins/Class_remi/icon.png"), "Class_remi", self.iface.mainWindow())
        
        # connect the action to the run method
        self.action.triggered.connect(self.run)
         
        # Add toolbar button and menu item
        self.iface.addToolBarIcon(self.action)
        self.iface.addPluginToVectorMenu("&Class_remi", self.action)
        

    def unload(self):
        # Remove the plugin menu item and icon
        self.iface.removePluginVectorMenu("&Class_remi", self.action)
        self.iface.removeToolBarIcon(self.action)

    def run(self):
        """Run method that performs all the real work"""
        # show the dialog
        self.dlg.init_before_show()
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed
        if result == 1:
            # Do something useful here - delete the line containing pass and
            # substitute with your code.
            self.load_line()
            self.load_arrets()
            self.test()
            
       
    def load_line(self):
        uri = QgsDataSourceURI()
        # set host name, port, database name, username and password
        uri.setConnection("localhost", "5432", "postgres", "postgres", "210893")
        # set database schema, table name, geometry column and optionally
        # subset (WHERE clause)
        uri.setDataSource("public", "ligne", "geom")
        vlayer1 = QgsVectorLayer(uri.uri(), "ligne_tan", "postgres")
    
    
    def load_arrets(self):
        uri = QgsDataSourceURI()
        # set host name, port, database name, username and password
        uri.setConnection("localhost", "5432", "postgres", "postgres", "210893")
        # set database schema, table name, geometry column and optionally
        # subset (WHERE clause)
        uri.setDataSource("public", "arrettan", "geom")
        vlayer2 = QgsVectorLayer(uri.uri(), "arrets_tan", "postgres")
        
    def test(self):
        ligne_tan = self.dlg.ui.Ligne_choix.currentText()
        arrets_tan = self.dlg.ui.arrets_choix.currentText()

Dernière modification par Spynz (Mon 16 March 2015 17:14)

Hors ligne

 

#4 Mon 16 March 2015 19:11

SANTANNA
Moderateur
Lieu: Angers
Date d'inscription: 18 Jan 2008
Messages: 3799

Re: QGIS : Creation de Plugin ?

En faisant cela, la commande m'indique que "pyrcc4" n'est pas connu, ce qui ne m'étonne pas.


Ça devrait marcher comme cela sauf qu'il faut avoir indiqué le dossier où se trouve pyrcc4 (un des dossiers bin sous C:\QGIS... - désolé, je n'ai pas la version standalone) dans le Path de windows. Sinon, il faudrait indiquer tout le chemin vers pyrcc4.
Pour l'autre point, le numéro de la ligne qui pose problème devrait être dans le message d'erreur. Et si j'ai bien vu, remplacez

Code:

self.dlg = Class_remiDialog(self.iface)

par

Code:

self.dlg = Class_remiDialog()

. En principe ces paramétrages sont configurés par Plugin Builder donc si besoin de les modifier, commentez la ligne existante avant de faire les tests. Ainsi, vous pourrez facilement déboguer.

Hors ligne

 

#5 Thu 19 March 2015 18:32

Spynz
Juste Inscrit !
Date d'inscription: 14 Mar 2015
Messages: 6

Re: QGIS : Creation de Plugin ?

Merci beaucoup.
J'ai finalement réussi à ne plus avoir l'erreur avec le resources, en le compilant comme vous me l'avez expliqué. Mais j'ai maintenant un autre problème qui apparaît dès l'ouverture de QGIS :

Code:

NameError: global name 'ui_Class_remi' is not defined

'ui_Class_remi' est appelé dans mon fichier dialog dont le code est le suivant :

Code:

# To change this license header, choose License Headers in Project Properties.
# To change this template file, choose Tools | Templates
# and open the template in the editor.

__author__ = "guyon_000"
__date__ = "$16 mars 2015 15:18:04$"

# -*- coding: utf-8 -*-
"""
/***************************************************************************
 Class_remiDialog
                                 A QGIS plugin
 Description_remi
                             -------------------
        begin                : 2015-03-05
        git sha              : $Format:%H$
        copyright            : (C) 2015 by author_remi
        email                : igor.belot@orange.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os

from PyQt4 import QtGui, uic

FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'Module_name_remi_dialog_base.ui'))


class Class_remiDialog(QtGui.QDialog, FORM_CLASS):
    def __init__(self, parent=None):
        """Constructor."""
        super(Class_remiDialog, self).__init__(parent)
        self.ui = ui_Class_remi()
        self.setupUi(self)
        self.iface = iface
        self.settings = QSettings()
        self.mc = self.iface.mapCanvas()
        self.legend = self.iface.legendInterface()
        self.loaded_layers = self.legend.layers()
        # selected layer
        self.vlayer = self.mc.currentLayer()
        # Clear form
        self.ui.Ligne_choix.clear()
        # UI CCONNECTORS
        self.ui.button_box.accepted.connect(self.run)
        self.ui.button_box.rejected.connect(self.close)
         #self.ui.comboBox_inputlayer.currentIndexChanged.connect(self.update_fields)
        self.ui.Ligne_choix.activated.connect(self.update_fields)
        self.ui.arrets_choix.activated.connect(self.update_fiels)
        
       
       

    def init_before_show(self):
        # Get layers from legend
        self.mc = self.iface.mapCanvas()
        self.legend = self.iface.legendInterface()
        self.loaded_layers = self.legend.layers()
        self.ui.Ligne_choix.clear()
        
        # Populate comboboxes and fields
        list_of_vlayers = self.get_useful_layers()
        if len(list_of_vlayers) > 0:
            self.ui.Ligne_choix.addItems(list_of_vlayers)
            self.update_working_layer()
            self.update_fields()
        else:
            self.iface.messageBar().pushMessage("Error", "Plugin needs a valid vector layer loaded.", level=QgsMessageBar.CRITICAL, duration=5)

    def update_working_layer(self):
        for layer in self.loaded_layers:
            if layer.name() == self.ui.Ligne_choix.currentText():
                self.vlayer = layer
                break
                
    def get_useful_layers(self):
      self.vector_line_layers = {}
      for layer in self.loaded_layers:
            fields_names = []
            # select line vector layers
            if (layer.type() == layer.VectorLayer) and (layer.geometryType() == QGis.Line):
                layer_info = [layer]
                provider = layer.dataProvider()
                fields = provider.fields()
                # get vector layer fields
                for field in fields:
                    if (field.type() == QVariant.Int or field.type() == QVariant.Double):
                        fields_names.append(field.name())
                layer_info += [fields_names]
                self.vector_line_layers[str(layer.name())] = layer_info
            else:
                pass
            vector_line_layers = list(self.vector_line_layers)
            return vector_line_layers

    def update_fields(self):
        self.update_working_layer()

    def run(self):
        pass
        return

Je suis quasiment sûr que cela vient du fait que, même si j'ai pu compiler le fichier resources, je n'ai pas réussi à compiler mon module principal 'Module_name.py'.
J'ai mis en pièce jointe ma compilation et l'erreur qu'elle me renvoit.


Merci d'avance!

Dernière modification par Spynz (Thu 19 March 2015 19:11)


Fichier(s) joint(s) :
Pour accéder aux fichiers vous devez vous inscrire.

Hors ligne

 

#6 Thu 19 March 2015 22:14

gvellut
Participant actif
Lieu: Annecy
Date d'inscription: 13 Apr 2006
Messages: 112
Site web

Re: QGIS : Creation de Plugin ?

Plusieurs choses:
- Si jamais tu as installé QGIS via OSGEO4W: Pour ouvrir la ligne de commande avec un PATH adapté à QGIS (par exemple pour inclure Python ou les outils pyuic4 ou pyrcc4, qui sont installés avec QGIS), tu peux lancer la commande OSGEO4W.bat (qui est installée en même temps que QGIS et accessible via le menu Démarrer).
- Dans ton cas, tu n'as pas besoin de compiler les .ui en .py: L'appel à uic.loadUiType dans ton dialogue s'occupe de charger le .ui dynamiquement au chargement du fichier.
- Pourquoi as-tu ajouté la ligne self.ui = ui_Class_remi() ? Elle ne semble pas nécessaire: Class_remiDialog hérite déjà de la FORM_CLASS (définie dans le .ui). Là où dans le code tu utilises self.ui (par exemple, self.ui.button_box, tu peux remplacer par self (par exemple self.button_box).
- tu as une autre erreur: tu références iface (self.iface=iface) mais il n'y a pas de iface définie localement (peut-être l'ajouter aux arguments du constructeur).

Dernière modification par gvellut (Thu 19 March 2015 22:18)

Hors ligne

 

#7 Fri 20 March 2015 11:09

Spynz
Juste Inscrit !
Date d'inscription: 14 Mar 2015
Messages: 6

Re: QGIS : Creation de Plugin ?

Merci pour ta réponse, j'ai réussi à compiler mon fichier .ui mais c'est vrai que je n'en avais pas besoin grâce à la FORM_CLASS. Cela me semble plus correct comme cela:

Code:

# To change this license header, choose License Headers in Project Properties.
# To change this template file, choose Tools | Templates
# and open the template in the editor.

__author__ = "guyon_000"
__date__ = "$16 mars 2015 15:18:04$"

# -*- coding: utf-8 -*-
"""
/***************************************************************************
 Class_remiDialog
                                 A QGIS plugin
 Description_remi
                             -------------------
        begin                : 2015-03-05
        git sha              : $Format:%H$
        copyright            : (C) 2015 by author_remi
        email                : igor.belot@orange.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os

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

FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'Module_name_remi_dialog_base.ui'))


class Class_remiDialog(QtGui.QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(Class_remiDialog, self).__init__(parent)
        self.setupUi(self)
        self.iface = iface
        self.settings = QSettings()
        self.mc = self.iface.mapCanvas()
        self.legend = self.iface.legendInterface()
        self.loaded_layers = self.legend.layers()
        # selected layer
        self.vlayer = self.mc.currentLayer()
        # Clear form
        self.Ligne_choix.clear()
        # UI CCONNECTORS
        self.button_box.accepted.connect(self.run)
        self.button_box.rejected.connect(self.close)
        
        self.Ligne_choix.activated.connect(self.update_fields)
        self.arrets_choix.activated.connect(self.update_fiels)
        
       
       

    def init_before_show(self):
        # Get layers from legend
        self.mc = self.iface.mapCanvas()
        self.legend = self.iface.legendInterface()
        self.loaded_layers = self.legend.layers()
        self.Ligne_choix.clear()
        
        # Populate comboboxes and fields
        list_of_vlayers = self.get_useful_layers()
        if len(list_of_vlayers) > 0:
            self.Ligne_choix.addItems(list_of_vlayers)
            self.update_working_layer()
            self.update_fields()
        else:
            self.iface.messageBar().pushMessage("Error", "Plugin needs a valid vector layer loaded.", level=QgsMessageBar.CRITICAL, duration=5)

    def update_working_layer(self):
        for layer in self.loaded_layers:
            if layer.name() == self.Ligne_choix.currentText():
                self.vlayer = layer
                break
                
    def get_useful_layers(self):
      self.vector_line_layers = {}
      for layer in self.loaded_layers:
            fields_names = []
            # select line vector layers
            if (layer.type() == layer.VectorLayer) and (layer.geometryType() == QGis.Line):
                layer_info = [layer]
                provider = layer.dataProvider()
                fields = provider.fields()
                # get vector layer fields
                for field in fields:
                    if (field.type() == QVariant.Int or field.type() == QVariant.Double):
                        fields_names.append(field.name())
                layer_info += [fields_names]
                self.vector_line_layers[str(layer.name())] = layer_info
            else:
                pass
            vector_line_layers = list(self.vector_line_layers)
            return vector_line_layers

    def update_fields(self):
        self.update_working_layer()

    def run(self):
        pass
        return

J'ai malheureusement toujours une erreur et je n'arrive pas à voir pourquoi (désolé je débute en Python, je fais beaucoup d'erreurs sûrement élémentaires...):

Code:

AttributeError: type object 'QDialog' has no attribute 'mapCanvas'

Hors ligne

 

#8 Fri 20 March 2015 12:02

gvellut
Participant actif
Lieu: Annecy
Date d'inscription: 13 Apr 2006
Messages: 112
Site web

Re: QGIS : Creation de Plugin ?

Regarde l'appel au constructeur de Class_remiDialog: l'appel n'a peut-être pas tous les arguments (notamment iface, comme tu viens de l'ajouter).

Hors ligne

 

#9 Fri 20 March 2015 15:20

Spynz
Juste Inscrit !
Date d'inscription: 14 Mar 2015
Messages: 6

Re: QGIS : Creation de Plugin ?

Super ça marche!!
Merci beaucoup! Je vais continuer à écrire mon code et reviendrai sur le forum en cas de problème smile

Hors ligne

 

#10 Sat 21 March 2015 18:56

Spynz
Juste Inscrit !
Date d'inscription: 14 Mar 2015
Messages: 6

Re: QGIS : Creation de Plugin ?

Cela fait plusieurs jours que je suis bloqué dans mon code du Plugin. En effet, je n'arrive pas à afficher dans ma comboBox (appelée Ligne_choix) les layers présents dans QGIS.

Voici mon code de dialogue:

Code:

# To change this license header, choose License Headers in Project Properties.
# To change this template file, choose Tools | Templates
# and open the template in the editor.

__author__ = "guyon_000"
__date__ = "$16 mars 2015 15:18:04$"

# -*- coding: utf-8 -*-
"""
/***************************************************************************
 Class_remiDialog
                                 A QGIS plugin
 Description_remi
                             -------------------
        begin                : 2015-03-05
        git sha              : $Format:%H$
        copyright            : (C) 2015 by author_remi
        email                : igor.belot@orange.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os

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

FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'Module_name_remi_dialog_base.ui'))


class Class_remiDialog(QtGui.QDialog, FORM_CLASS):
    def __init__(self, iface, parent=None):
        """Constructor."""
        super(Class_remiDialog, self).__init__(parent)
        self.setupUi(self)
        self.iface = iface
        self.settings = QSettings()
        
        self.mc = self.iface.mapCanvas()
        self.legend = self.iface.legendInterface()
        self.loaded_layers = self.legend.layers()
        # selected layer
        self.vlayer = self.mc.currentLayer()
        
        # Clear form
        self.Ligne_choix.clear()
        # UI CCONNECTORS
        self.button_box.accepted.connect(self.run)
        self.button_box.rejected.connect(self.close)
    self.Ligne_choix.activated.connect(self.update_working_layer)
        self.pushButtonBrowseOutput.clicked.connect(self.output_shp_path)
        

    def init_before_show(self):
        # Get layers from legend
        self.mc = self.iface.mapCanvas()
        self.legend = self.iface.legendInterface()
        self.loaded_layers = self.legend.layers()
        
        # Populate comboboxes and fields
        self.Ligne_choix.clear()
        list_of_vlayers = self.get_useful_layers()
        if len(list_of_vlayers) > 0:
            self.Ligne_choix.addItems(list_of_vlayers)
            self.update_working_layer()
        else:
            self.iface.messageBar().pushMessage("Error", "Plugin needs a valid vector layer loaded.", level=QgsMessageBar.CRITICAL, duration=5)
        

    def update_working_layer(self):
        for layer in self.loaded_layers:
            if layer.name() == self.Ligne_choix.currentText():
                self.vlayer = layer
                break
                
    def get_useful_layers(self):
      self.vector_line_layers = {}
      for layer in self.loaded_layers:
            fields_names = []
            # select line vector layers
            if (layer.type() == QgsMapLayer.VectorLayer) and (layer.geometryType() == QGis.WKBLineString):
                layer_info = [layer]
                provider = layer.dataProvider()
                fields = provider.field()
                # get vector layer fields
                for field in fields:
                    if (field.type() == QVariant.Int or field.type() == QVariant.Double):
                        fields_names.append(field.name())
                layer_info += [fields_names]
                self.vector_line_layers[str(layer.name())] = layer_info
            else:
                pass
            vector_line_layers = list(self.vector_line_layers)
            return vector_line_layers

    def run(self):
        pass
        return
    
    def output_shp_path(self):
        self.lineEdit_outputfile.clear()
        lastDir = self.settings.value("/LabelLayer/lastDir")
        self.savelayerPath = QFileDialog.getSaveFileName(None, "Creer un shapefile en sortie", lastDir, "*.shp")
        if not self.savelayerPath:
            return
        self.lineEdit_outputfile.setText(self.savelayerPath)

        file_info = QFileInfo(self.savelayerPath)
        self.layer_name = file_info.completeBaseName()
        self.layer_dir = file_info.absolutePath()
        self.settings.setValue("/LabelLayer/lastDir", str(self.layer_dir))

Je sélectionne dans "get useful layers" les layers étant des lignes (j'en ai plusieurs d'ouvertes et actives dans QGIS) mais pourtant, je reçois toujours l'erreur

Code:

Error: Plugin needs a valid vector layer loaded.

, erreur que j'ai demandé d'afficher s'il n'y avait aucun layer de géométrie de type ligne.
J'ai essayé plusieurs choses, notamment changer le chargement de mes layers (avec self.iface.legendInterface(), ou avec layers = self.iface.mapCanvas().layers() ...) mais en vain...
Je ne comprends vraiment pas pourquoi ils ne s'affichent pas.

Merci d'avance pour votre aide

Dernière modification par Spynz (Sat 21 March 2015 18:56)

Hors ligne

 

#11 Sun 22 March 2015 20:10

SANTANNA
Moderateur
Lieu: Angers
Date d'inscription: 18 Jan 2008
Messages: 3799

Re: QGIS : Creation de Plugin ?

Bonsoir,
Je ne suis pas non plus expert en Python (et ne l'ai abordé que récemment ayant eu besoin d'un plugin) mais si je puis me permettre quelques conseils...
Pour vérifier le code, un test dans la console Python est assez pratique (J'ai d'ailleurs modifié mon premier message pour y ajouter une nouvelle ressource : la Console Python de QGIS). Faire fréquemment des print (par ex) pour voir ce qui est retourné après quelques lignes permet de bien comprendre le processus et l'avancement du code (il n'y a rien de mieux, je vous assure). Sans oublier que cela permet de faire un code fonctionnel pas forcément dépendant de l'interface (et donc facilement mobilisable dans un autre contexte de script).
Quand je teste la fonction get_useful_layers pas à pas dans la console, ça renvoie "AttributeError: 'QgsVectorDataProvider' object has no attribute 'field' '(mais plutôt fields)" après la ligne fields = provider.field(). C'est peut-être juste une faute de recopie...
Et plus loin, la conversion en liste de vector_line_layers semble poser problème.

Pour déboguer, la doc officielle de QGIS propose également des pistes et comme je l'avais déjà suggéré plus haut, les anciens plugins. vous n'êtes pas le premier à vouloir récupérer dans une liste déroulante des noms de couches. Sans avoir consulté leur code (et ce n'est peut-être pas ce qu'il y a de plus optimisé), je vois que des plugins comme GroupStats, StationLines, DissolvewithStats font quelque chose du genre. Vous y trouverez surement des bouts de code pratique.

Dernière modification par SANTANNA (Sun 22 March 2015 20:38)

Hors ligne

 

Pied de page des forums

Powered by FluxBB