[GIS] Problem creating point shapefiles programmatically using python in QGIS 2.2

pointpythonqgisshapefile

I am trying to create a point shapefile in the memory buffer (for a temporary label) and then zoom to the extents on this buffer. The working (in version 2.1) test code for this is:

def originalFunction():
    vl = QgsVectorLayer("point?crs=epsg:27700", "temporary_points", "memory")
    pr = vl.dataProvider()
    # Enter editing mode
    vl.startEditing()
    count = 0
    while count < 10:
        # add a feature
        fet = QgsFeature()
        fet.setGeometry( QgsGeometry.fromPoint(QgsPoint((376000+count),(408000+count))) )
        vl.addAttribute(QgsField("mytext", QVariant.String, "", 255))
        vl.addAttribute(QgsField("mytext2", QVariant.String, "", 255))
        fet.initAttributes (2)
        fet.setAttribute(0,"hello")
        fet.setAttribute(1,"hello")
        pr.addFeatures( [ fet ] )
        count+=1
    # Commit changes
    vl.commitChanges()
    QgsMapLayerRegistry.instance().addMapLayer(vl)
    canvas = qgis.utils.iface.mapCanvas()
    qgis.utils.iface.setActiveLayer(vl)#This is done so the zoom to extent works
    qgis.utils.iface.zoomToActiveLayer()#Unless this happens the extent seems to #include the origin
    canvas.zoomByFactor(1)#this time the zoom works

This code should create a line of points diagonally and zoom to their extent in version 2.1.
When I try and run the same code in the new version (2.2 primarily but also 2.3) it does not work (no points are generated, and the fix for zooming to extent no longer seems to be working either).

I have looked at the cookbook here: http://www.qgis.org/en/docs/pyqgis_developer_cookbook/vector.html#modifying-vector-layers and tried to use that as a guide to rebuild the function. However my result (below) does not seem to be operational, despite deviating from the example code as little as I can (I found one of the functions in the example did not exist for the object it was being called on so had to replace it as shown in my comments).

New Function:

def testFunction():
    # create layer
    vl = QgsVectorLayer("point?crs=epsg:27700", "temporary_points", "memory")
    pr = vl.dataProvider()
    caps = vl.dataProvider().capabilities()

    if caps & QgsVectorDataProvider.AddAttributes:
        res = vl.dataProvider().addAttributes( [ QgsField("mytext", \
    QVariant.String), QgsField("mytext2", \
    QVariant.String) ] )
    print vl.updateFields()
    count = 0
    while count < 10:
        if caps & QgsVectorDataProvider.AddFeatures:
            feat = QgsFeature()
            feat.initAttributes (2)
#            feat.addAttribute(0,"hello")#Did not work, gave error: object has no attribute 'addAttribute'
            feat.setAttribute(0,"hello")
            feat.setAttribute(1,"hello")
            feat.setGeometry( QgsGeometry.fromPoint(QgsPoint((376000+count),(408000+count))) )
            (res, outFeats) = vl.dataProvider().addFeatures( [ feat ] )
            count+=1
    QgsMapLayerRegistry.instance().addMapLayer(vl)
    canvas = qgis.utils.iface.mapCanvas()
    qgis.utils.iface.setActiveLayer(vl)#no longer fixes the zooming to extent bug
    qgis.utils.iface.zoomToActiveLayer()
    canvas.zoomByFactor(1)
    canvas.setExtent(vl.extent())

Thanks for reading, I apologize for the length but I wanted to include code so that others can replicate the problem and see where I am going wrong!

Best Answer

You forgot canvas.refresh()

canvas.zoomByFactor(6)
canvas.zoomToPreviousExtent()
canvas.zoomWithCenter(50,150,2)
canvas.zoomToFullExtent()
# but
canvas.setExtent(v1.extent())
canvas.refresh()

New

If you reed carefully the memory layer documentation, you can simplify your script:

# define your fields in the  QgsVectorLayer
vl = QgsVectorLayer("Point?crs=epsg:27700&field=mytext:string(255)&field=mytext2:string(255)", "temporary_points", "memory")
pr = vl.dataProvider()
for count in range(10):
    # add a feature
    fet = QgsFeature()
    fet.setGeometry( QgsGeometry.fromPoint(QgsPoint((376000+count),(408000+count))) )
    # add attributes (list)
    fet.setAttributes(["hello","hello"])
    pr.addFeatures( [ fet ] )
    vl.updateExtents()

QgsMapLayerRegistry.instance().addMapLayer(vl)

and if we examine the extents:

# extent of the layer
print vl.extent().asWktCoordinates()
0 0, 376009 408009

but if I save the memory layer as a shapefile:

print mylayer.extent().asWktCoordinates()
376000 408000, 376009 408009

so it seems that it is a problem of extent with memory layers:

If I select all the features:

vl.selectAll()
print vl.boundingBoxOfSelected().asWktCoordinates()
376000 408000, 376009 408009
vl.setExtent(vl.boundingBoxOfSelected())
print vl.extent().asWktCoordinates()
376000 408000, 376009 408009

And the zoom works well

Related Question