Estou com alguns problemas ao trabalhar com a API QGIS para python. Fiquei mais confortável trabalhando no console python no QGIS, mas encontro problemas ao tentar executar o código fora do QGIS.
Basicamente, quero pegar um shapefile, rotulá-lo com base no nome do atributo especificado e renderizar uma imagem. O código funciona no QGIS, mas não funciona fora do QGIS. Então, de onde vem o meu problema?
import sys
import qgis
import PyQt4
from qgis.core import *
from qgis.utils import *
from qgis.gui import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
#initialize QGIS
QgsApplication.setPrefixPath( r"C:\OSGeo4W64\apps\qgis", True )
QgsApplication.initQgis()
#Add layer to instance
file = QgsVectorLayer("Good Shape File", "BMAS", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(file)
#Adjust layer Settings
#Code sample from http://gis.stackexchange.com/questions/77870/how-to-label-vector-features-programmatically
palyr = QgsPalLayerSettings()
palyr.enabled = True
palyr.fieldName = 'Attribute'
palyr.placement= QgsPalLayerSettings.OverPoint
palyr.setDataDefinedProperty(QgsPalLayerSettings.Size,True,True,'8','')
palyr.writeToLayer(file)
if file.isValid():
print "File is valid."
mapRenderer = iface.mapCanvas().mapRenderer()
lst = [file.id()]
mapRenderer.setLayerSet(lst)
mapRenderer.setLayerSet( lst )
c = QgsComposition(mapRenderer)
c.setPlotStyle(QgsComposition.Print)
x, y = 0, 0
w, h = c.paperWidth(), c.paperHeight()
composerMap = QgsComposerMap(c, x,y,w,h)
c.addItem(composerMap)
composerLabel = QgsComposerLabel(c)
composerLabel.adjustSizeToText()
c.addItem(composerLabel)
composerLabel.setItemPosition(20,10)
composerLabel.setItemPosition(20,10, 100, 30)
legend = QgsComposerLegend(c)
legend.model().setLayerSet(mapRenderer.layerSet())
c.addItem(legend)
#set image sizing
dpi = c.printResolution()
dpmm = dpi / 25.4
width = int(dpmm * c.paperWidth())
height = int(dpmm * c.paperHeight())
img = QImage(QSize(width, height), QImage.Format_ARGB32)
img.setDotsPerMeterX(dpmm * 1000)
img.setDotsPerMeterY(dpmm * 1000)
img.fill(0)
imagePainter = QPainter(img)
sourceArea = QRectF(0, 0, c.paperWidth(), c.paperHeight())
targetArea = QRectF(0, 0, width, height)
#renders image
c.render(imagePainter, targetArea, sourceArea)
imagePainter.end()
img.save("E:/QGisTestImages/out.png", "png")
Sou capaz de fazer o exemplo de renderização simples no livro de receitas python, então acho que meus caminhos estão configurados corretamente.
"Arquivo de boa forma" deve ser substituído por um bom local de caminho, se você deseja executar isso. E palyr.fieldName = 'Attribute' deve ser definido como um nome de campo válido para esse shapefile.
Edit: Eu me livrei do iface e inseri o código pela extensão entre a inicialização do mapRenderer e a declaração lst.
mapRenderer = QgsMapRenderer()
rect = file.extent()
mapRenderer.setExtent(rect)
mapRenderer.setLabelingEngine(QgsPalLabeling())
lst = [file.id()]
Editar: eu adicionei
app = QgsApplication([], True)
depois de
QgsApplication.initQgis()
e o código funcionou.
iface
fora do QGIS. Isso precisa sermapRenderer = QgsMapRenderer()
Respostas:
A combinação de remover iface e declarar a variável do aplicativo parece ter funcionado. Agora eu recebo uma imagem renderizada do shapefile com cada recurso rotulado com o atributo com base em 'Atributo'.
fonte