Comment changer la valeur d'un attribut en utilisant QgsFeature dans PyQGIS?

12

Je voudrais mettre à jour un attribut d'une fonctionnalité. Cependant, je ne sais pas le mettre à jour en utilisant l'objet de fonctionnalité. Je dois utiliser le fournisseur de données pour le mettre à jour.

layers = QgsMapLayerRegistry.instance().mapLayersByName('my_line') 
layer = layers[0]
dp = layer.dataProvider()
it = dp.getFeatures()

for i in range(0, dp.featureCount()):
  feat = it.next()
  attrs = { 2 : 30 }
  layer.dataProvider().changeAttributeValues({ feat.id() : attrs })

Puis-je changer la valeur d'un attribut à l'aide d'un QgsFeatureobjet?

De plus, est-il possible de boucler en utilisant un objet itérateur?

wannik
la source
comment puis-je changer les valeurs sans utiliser l'index? Je voudrais changer les valeurs en nommant leur nom de champ. Ce serait beaucoup plus confortable. Merci beaucoup! Salutations Robert
Robert BK
Utilisez simplement my_index = layer.fieldNameIndex("my_field_name")pour obtenir l'index.
Germán Carrillo
dans ce cas, je ne peux pas ajouter dans le champ la chaîne comment je peux faire?
Hamed Makian
Si vous avez une nouvelle question, veuillez la poser en cliquant sur le bouton Poser une question . Incluez un lien vers cette question si cela permet de fournir un contexte. - De l'avis
Dan C
Hamed, Bienvenue sur GIS Stack Exchange! Étant donné que cette question a déjà reçu une réponse, veuillez la poser comme une nouvelle question distincte ici gis.stackexchange.com/questions/ask .
cm1

Réponses:

17

Répondre à vos deux questions:

  1. Vous pouvez modifier vos valeurs d'entité à partir de l' layerobjet, pas besoin d'accéder à dataProvider().

  2. Oui, vous pouvez utiliser l'itérateur en forboucle.

Vérifiez le code ci-dessous:

layers = QgsMapLayerRegistry.instance().mapLayersByName('my_line') 
layer = layers[0]
it = layer.getFeatures()

layer.startEditing()
for feat in it:
  layer.changeAttributeValue(feat.id(), 2, 30)

layer.commitChanges()

Cela met à jour la troisième valeur de champ (index 2) à 30 pour toutes les entités de couche.


Remarque: Comme vous l'avez souligné, pour une raison quelconque, l'objet QgsFeature ne peut pas mettre à jour les valeurs des fonctionnalités, bien que l'API le dise.

Germán Carrillo
la source
5

Oui, mais vous devez connaître l'index du champ:

QgsFeature::setAttribute(int field,const QVariant & attr )  

Vous pouvez obtenir les champs à l'aide QgsFeature::fields, puis les parcourir jusqu'à ce que vous trouviez celui que vous souhaitez ou QgsFeature::attribute(const QString & name )pour trouver l'index de champ par nom.

La raison de QVariant est que setAttribute peut prendre des types Integer, Float, Date et Text. QgsFeature.attribute (nom) retourne également une variante de type int si l'attribut est trouvé et autre chose s'il ne peut pas être trouvé. Soyez conscient de cela dans votre code. Un bloc try..except serait garanti, essayez de convertir en int et sauf si le type n'est pas int.

Il est possible que votre fonctionnalité ne prenne pas en charge cette méthode. Une autre méthode que j'ai employée est QgsVectorLayer::changeAttributeValue:

self.canvas.currentLayer().changeAttributeValue(UpdateFeatureID,FieldToUpdate,self.CurrentWidget.text(),True)

Cela indique à la couche de mettre à jour une fonctionnalité et un attribut spécifiques. Dans l'exemple, la valeur provient d'un widget.

Michael Stimson
la source
J'ai essayé feat.setAttribute(1, QVariant(20))mais le système a dit TypeError: PyQt4.QtCore.QVariant représente un type mappé et ne peut pas être instancié
wannik
feat.setAttribute (1, 20) est la façon dont je l'ai fait auparavant. C'est mettre la valeur '20' dans l'attribut 1.
Michael Stimson
J'ai essayé feat.setAttribute(1, 20)mais les valeurs ne changent pas. Cependant, je peuxprint(feat.attributes()[1])
wannik
Voir les modifications, vous devrez peut-être appeler QgsVectorLayer.changeAttributeValue qui devrait utiliser le pilote pour effectuer les modifications.
Michael Stimson