Como alterar o valor de um atributo usando QgsFeature no PyQGIS?

12

Gostaria de atualizar um atributo de um recurso. No entanto, não sei atualizá-lo usando o objeto de recurso. Eu tenho que usar o provedor de dados para atualizá-lo.

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

Posso alterar o valor de um atributo usando o QgsFeatureobjeto?

Além disso, é possível fazer um loop usando um objeto iterador?

wannik
fonte
como posso alterar valores sem usar o índice? Gostaria de alterar os valores nomeando o nome do campo. Isso seria muito mais confortável. Muito obrigado! Saudações Robert
Robert BK
Basta usar my_index = layer.fieldNameIndex("my_field_name")para obter o índice.
Germán Carrillo
neste caso, não consigo adicionar no campo a string como posso fazer?
precisa
Se você tiver uma nova pergunta, faça-o clicando no botão Fazer pergunta . Inclua um link para esta pergunta se ela ajudar a fornecer contexto. - Do comentário
Dan C
Hamed, Bem-vindo ao GIS Stack Exchange! Como essa pergunta já foi respondida, faça sua pergunta como uma pergunta nova e separada aqui gis.stackexchange.com/questions/ask .
Cm1 #

Respostas:

17

Respondendo às suas duas perguntas:

  1. Você pode alterar os valores dos recursos do layerobjeto, sem necessidade de acessar o dataProvider().

  2. Sim, você pode usar o iterador em um forloop.

Verifique o código abaixo:

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

Isso atualiza o terceiro valor do campo (índice 2) para 30 para todos os recursos da camada.


Nota: Como você apontou, por algum motivo, o objeto QgsFeature não pode atualizar os valores dos recursos, embora a API diga que pode.

Germán Carrillo
fonte
5

Sim, mas você precisa conhecer o índice do campo:

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

Você pode obter os campos usando QgsFeature::fieldse, em seguida, iterá-los até encontrar o que deseja ou QgsFeature::attribute(const QString & name )encontrar o índice do campo pelo nome.

O motivo do QVariant é que o setAttribute pode usar os tipos Inteiro, Flutuante, Data e Texto. QgsFeature.attribute (name) retorna uma variante também do tipo int se o atributo for encontrado e outra coisa se não puder ser encontrado. Esteja ciente disso no seu código. Um bloco try..except seria garantido, tente converter para int e, exceto se type não for int.

É possível que seu recurso não suporte esse método. Outro método que empreguei é QgsVectorLayer::changeAttributeValue:

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

Isso informa à camada para atualizar um recurso específico e um atributo específico. No caso de exemplo, o valor vem de um widget.

Michael Stimson
fonte
Eu tentei feat.setAttribute(1, QVariant(20)), mas o sistema disse TypeError: PyQt4.QtCore.QVariant representa um tipo mapeados e não pode ser instanciado
wannik
feat.setAttribute (1, 20) é como eu fiz isso antes. Isso é colocar o valor '20' em atributo 1.
Michael Stimson
Eu tentei, feat.setAttribute(1, 20)mas os valores não mudam. No entanto, eu possoprint(feat.attributes()[1])
wannik
Veja as edições, talvez você precise chamar o QgsVectorLayer.changeAttributeValue, que deve usar o driver para fazer as alterações.
Michael Stimson