J'avais un plugin fonctionnel dans QGIS 1.8 qui lisait les données d'une base de données MSAccess et les ajoutait à une série de couches de mémoire. Il y a un certain traitement impliqué dans l'intérim, donc je ne pense pas que simplement utiliser QGIS pour lire directement à partir de la base de données soit une option.
Je voudrais passer de QGIS 1.8 à 1.9 (principalement en raison de la qualité améliorée du compositeur d'impression). Le plugin ne fonctionne pas avec la nouvelle API.
J'ai essayé une variété de méthodes qui sont apparues dans les recherches Google. Un, en modifiant le code ci-dessous - à partir de http://www.qgis.org/pyqgis-cookbook/vector.html#memory-provider , c'est-à-dire en ajoutant la géométrie et les attributs au fournisseur de données puis en mettant à jour la couche - pour l'adapter à la nouvelle API. un peu mais les attributs n'étaient pas visibles jusqu'à ce que j'entre en mode édition (similaire à http://hub.qgis.org/issues/3713 ). Une approche alternative, détaillée dans la réponse n ° 1 du lien ci-dessus, a ajouté la couche et les attributs correctement, mais je n'ai pas pu ajouter de fonctionnalités à la couche.
Étant donné que cela devrait être une tâche assez simple, j'espère que quelqu'un ici pourra offrir un exemple pratique de la façon dont cela devrait être fait. (PS, je ne suis pas un programmeur professionnel et la plupart de mon codage est assez grossier - je me réjouis de tout conseil, mais je vous demande pardon de votre ignorance)
# Receivers = a list of lists returned from a database query
# create layer
vl = QgsVectorLayer("Point", item, "memory")
pr = vl.dataProvider()
# add fields
pr.addAttributes( [ QgsField("Rec_No", QVariant.Int), QgsField("Include", QVariant.String), QgsField("Label", QVariant.String), QgsField("X", QVariant.Double),
QgsField("Y", QVariant.Double), QgsField("Z", QVariant.Double), QgsField("Height", QVariant.Double),
QgsField("Project_Re", QVariant.String), QgsField("NCA", QVariant.String),
QgsField("DayCrit", QVariant.Int), QgsField("EveCrit", QVariant.Int), QgsField("NightCrit", QVariant.Int) ] )
for i in range(len(Receivers)):
# add a feature
fet = QgsFeature()
X = Receivers[i][3]
Y = Receivers[i][4]
fet.setGeometry( QgsGeometry.fromPoint(QgsPoint(X,Y)) )
# Details = a list of results returned from a database query specific to each result in 'Receivers'
if Receivers[i][3] != 0:
Include = 'Yes'
else:
Include = 'No'
fet.setAttributeMap( { 0 : QVariant(Receivers[i][0]), 1 : QVariant(Include), 2 : QVariant(Receivers[i][2]),
3 : QVariant(Receivers[i][3]), 4 : QVariant(Receivers[i][4]), 5 : QVariant(Receivers[i][5]), 6 : QVariant(Receivers[i][6]),
7 : QVariant(Details[0]), 8 : QVariant(Details[1]), 9 : QVariant(Details[2]), 10 : QVariant(Details[3]), 11 : QVariant(Details[4]) } )
pr.addFeatures( [ fet ] )
# add a style
vl.loadNamedStyle('C:/OSGeo4W/apps/qgis/python/plugins/Gopher2QGIS/styles/Receiver_Style.qml')
# update layer's extent when new features have been added
# because change of extent in provider is not propagated to the layer
vl.commitChanges()
vl.updateExtents()
vl.updateFieldMap()
QgsMapLayerRegistry.instance().addMapLayer(vl)
Réponses:
Merci à gsherman ci-dessus, l'exemple de plugin PinPoint est parfait.
Si je comprends bien, le processus est le suivant:
Voici un extrait de mon code qui fonctionne maintenant.
la source
Sur la base de la réponse d'Adam Bioletti, d'autres tests du processus décrit montrent que la seule exigence essentielle est de commencer à éditer la couche mémoire avant d' apporter des modifications, telles que la création d'attributs et de fonctionnalités, puis de valider les modifications. Cela peut être fait avant d'ajouter la couche au mappage du registre.
Voici une mise à jour du code du Cookbook qui fonctionne avec l'API 2.0:
la source