Jak zmienić wartość atrybutu za pomocą QgsFeature w PyQGIS?

12

Chciałbym zaktualizować jeden atrybut funkcji. Nie wiem jednak, jak go zaktualizować za pomocą obiektu funkcji. Muszę użyć dostawcy danych, aby go zaktualizować.

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

Czy mogę zmienić wartość atrybutu za pomocą QgsFeatureobiektu?

Co więcej, czy można zapętlić za pomocą obiektu iteratora?

wannik
źródło
jak mogę zmienić wartości bez korzystania z indeksu? Chciałbym zmienić wartości, nazywając ich nazwę pola. To byłoby znacznie wygodniejsze. Dziękuję Ci bardzo! Pozdrowienia Robert
Robert BK
Wystarczy użyć, my_index = layer.fieldNameIndex("my_field_name")aby uzyskać indeks.
Germán Carrillo
w takim przypadku nie mogę dodać w polu ciągu, jak mogę to zrobić?
Hamed Makian
Jeśli masz nowe pytanie, zadaj je, klikając przycisk Zadaj pytanie . Dołącz link do tego pytania, jeśli pomaga to w zapewnieniu kontekstu. - Z recenzji
Dan C
Hamed, Witamy w GIS Stack Exchange! Ponieważ na to pytanie już udzielono odpowiedzi, zadaj je jako nowe, osobne pytanie tutaj gis.stackexchange.com/questions/ask .
cm1

Odpowiedzi:

17

Odpowiadając na dwa pytania:

  1. Możesz zmienić wartości funkcji z layerobiektu, bez potrzeby dostępu do dataProvider().

  2. Tak, możesz używać iteratora w forpętli.

Sprawdź kod poniżej:

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

To aktualizuje wartość trzeciego pola (indeks 2) do 30 dla wszystkich funkcji warstwy.


Uwaga: Jak wskazałeś, z jakiegoś powodu obiekt QgsFeature nie może aktualizować wartości funkcji, chociaż API mówi, że może.

Germán Carrillo
źródło
5

Tak, ale musisz znać indeks pola:

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

Możesz uzyskać pola za pomocą, QgsFeature::fieldsa następnie iterować przez nie, aż znajdziesz to, które chcesz lub QgsFeature::attribute(const QString & name )indeks pola według nazwy.

Powodem QVariant jest to, że setAttribute może przyjmować typy Integer, Float, Date i Text. QgsFeature.attribute (nazwa) zwraca wariant również typu int, jeśli atrybut zostanie znaleziony, i coś innego, jeśli nie można go znaleźć. Pamiętaj o tym w swoim kodzie. Warunkiem jest blok try..except, spróbuj przekonwertować na int i chyba że typ nie jest int.

Możliwe, że twoja funkcja nie obsługuje tej metody. Inną metodą, którą zastosowałem jest QgsVectorLayer::changeAttributeValue:

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

Informuje warstwę, aby zaktualizowała określoną funkcję i określony atrybut. W tym przypadku wartość pochodzi z widżetu.

Michael Stimson
źródło
Próbowałem, feat.setAttribute(1, QVariant(20))ale system powiedział, że TypeError: PyQt4.QtCore.QVariant reprezentuje odwzorowany typ i nie można go utworzyć
wannik
feat.setAttribute (1, 20) to sposób, w jaki robiłem to wcześniej. To jest wartość „20” w atrybucie 1.
Michael Stimson
Próbowałem, feat.setAttribute(1, 20)ale wartości się nie zmieniają. Jednak mogęprint(feat.attributes()[1])
wannik
Zobacz zmiany, być może musisz wywołać QgsVectorLayer.changeAttributeValue, który powinien użyć sterownika do wprowadzenia zmian.
Michael Stimson