3

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!

2

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

  • Thanks, I have added a refresh at the end, but it does not seem to have made a difference, indeed the layers seem to not work with the native zoom to extent from the layers panel. – user24956 Feb 27 '14 at 17:24
  • see above the problem – gene Feb 27 '14 at 19:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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