8

I've been running into a few problems working with the QGIS API for python. I've gotten more comfortable working in the python console in QGIS but I run into problems when I try to run the code outside of QGIS.

Basically I want to take a shapefile, label it based on the specified attribute name, and render an image. The code works in QGIS, but does not work outside of of QGIS. So where is my problem coming from?

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

I'm able to do the simple rendering example in the python cookbook, so I think my paths are set up correctly.

"Good Shape File" should be replaced with a good path location if you want to run this. And palyr.fieldName = 'Attribute' should be set to a valid field name for that shapefile.

Edit: I have gotten rid of iface and inserted code for the extent between the mapRenderer initialization and the lst declaration.

mapRenderer = QgsMapRenderer()

rect = file.extent()
mapRenderer.setExtent(rect)
mapRenderer.setLabelingEngine(QgsPalLabeling())
lst = [file.id()]

Edit: I added

app = QgsApplication([], True)

after

QgsApplication.initQgis()

and the code worked.

5
  • 1
    For a start you can't use iface outside of QGIS. That needs to be mapRenderer = QgsMapRenderer()
    – Nathan W
    Jan 30, 2014 at 0:21
  • Alright, it appears I have not initialized mapRenderer with enough information. The console freezes at c = QgsComposition(mapRenderer) after I added the info on the extent of the layer and the labeling engine. The code still works in QGIS though, it just needs to be resized.
    – midfield99
    Jan 30, 2014 at 1:36
  • 1
    It appears that the initialization of QgsApplication was the problem. And it appears this problem was covered in gis.stackexchange.com/questions/69626/…. So declaring an app variable and adding an app.exitQgis() worked.
    – midfield99
    Jan 30, 2014 at 17:28
  • I am experiencing problems when creating pngs with aforementioned method. My shapefile is correctly read, a picture is created, but it always stays completely white. As you can see in the print-outs, the mapRenderer.extent() values are always zero. Is this normal, or do I need to dig deeper into this? The subsequent checks with dpi, width and height of the QgsComposition deliver some values, though I have no idea whether they are correct or not. I have also tried out a number of different printing/rendering options, as c.render(), or giving out the stuff as pdfs. I never get errors, but my pag
    – Bob3k
    May 26, 2014 at 21:00
  • Hey moderator that deleted my last post on the same topic, please leave this one up. This is completely relevant because I don't believe the answers above still work and I'm not the only one that's struggling here. Either I'm crazy, or the two bits of code no longer work. I've copied these and tweaked them for my use and for the life of me I can't get a tif from the shapefile with anything other than a white canvas that says 'Legend: Contours" in the top left corner. My goal is to take a shapefile (shp) and convert it to a tif with the contour lines labeled in elevation. I'm able to open the s
    – Marc
    Sep 1, 2015 at 12:23

1 Answer 1

2

The combination of removing iface and declaring the app variable seems to have worked. I now get an image rendered from the shapefile with each feature labeled with the attribute based on 'Attribute'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.