¿Cómo cambiar el valor de un atributo usando QgsFeature en PyQGIS?

12

Me gustaría actualizar un atributo de una característica. Sin embargo, no sé actualizarlo usando el objeto de función. Tengo que usar el proveedor de datos para actualizarlo.

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

¿Puedo cambiar el valor de un atributo usando un QgsFeatureobjeto?

Además, ¿es posible hacer un bucle con un objeto iterador?

wannik
fuente
¿Cómo puedo cambiar los valores sin usar el índice? Me gustaría cambiar los valores nombrando su nombre de campo. Eso sería mucho más cómodo. ¡Muchas gracias! Saludos Robert
Robert BK
Simplemente use my_index = layer.fieldNameIndex("my_field_name")para obtener el índice.
Germán Carrillo
en este caso no puedo agregar en el campo la cadena ¿cómo puedo hacerlo?
Hamed Makian
Si tiene una nueva pregunta, hágala haciendo clic en el botón Hacer pregunta . Incluya un enlace a esta pregunta si ayuda a proporcionar contexto. - De la opinión
Dan C
Hamed, ¡Bienvenido a GIS Stack Exchange! Como esta pregunta ya ha sido respondida, haga su pregunta como una pregunta nueva y separada aquí gis.stackexchange.com/questions/ask .
cm1

Respuestas:

17

Responde tus dos preguntas:

  1. Puede cambiar los valores de sus características desde el layerobjeto, sin necesidad de acceder a dataProvider().

  2. Sí, puedes usar el iterador en un forbucle.

Verifique el código a continuación:

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

Esto actualiza el tercer valor del campo (índice 2) a 30 para todas las entidades de capa.


Nota: Como señaló, por alguna razón el objeto QgsFeature no puede actualizar los valores de las características, aunque la API dice que sí.

Germán Carrillo
fuente
5

Sí, pero debes conocer el índice del campo:

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

Puede utilizar los campos QgsFeature::fieldsy luego recorrerlos en iteración hasta encontrar el que desea o QgsFeature::attribute(const QString & name )encontrar el índice de campo por nombre.

La razón de QVariant es que setAttribute puede tomar tipos enteros, flotantes, de fecha y de texto. QgsFeature.attribute (name) devuelve una variante también de tipo int si se encuentra el atributo y algo más si no se puede encontrar ... tenga en cuenta esto en su código. Se justificaría un bloque try..except, intente convertir a int y excepto si el tipo no es int.

Es posible que su función no sea compatible con este método. Otro método que he empleado es QgsVectorLayer::changeAttributeValue:

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

Esto le dice a la capa que actualice una característica específica y un atributo específico. En el caso de ejemplo, el valor proviene de un widget.

Michael Stimson
fuente
Lo intenté feat.setAttribute(1, QVariant(20))pero el sistema dijo TypeError: PyQt4.QtCore.QVariant representa un tipo mapeado y no puede ser instanciado
wannik
feat.setAttribute (1, 20) es como lo hice antes. Eso es poner el valor '20' en el atributo 1.
Michael Stimson
Lo intenté feat.setAttribute(1, 20)pero los valores no cambian. Sin embargo, puedoprint(feat.attributes()[1])
wannik
Vea las ediciones, quizás tenga que llamar a QgsVectorLayer.changeAttributeValue, que debe usar el controlador para realizar los cambios.
Michael Stimson