1

I have used following code for selecting the features one by one. but when i run the script it is just selecting last feature and zoom it. I want to select each feature and zoom it.

def SelectFeatures(self):
    layer = self.iface.activeLayer();
    iter = layer.getFeatures();
    for feature in iter:
        geom = feature.geometry()
        self.iface.mapCanvas().setSelectionColor(QColor("yellow"));
        layer.setSelectedFeatures([feature.id()])
        selected_features = layer.selectedFeatures()
        self.iface.mapCanvas().zoomToSelected( layer )
        self.iface.mapCanvas().refresh()
PolyGeo
  • 65,136
  • 29
  • 109
  • 338
Keyur Parmar
  • 417
  • 1
  • 5
  • 14

2 Answers2

2

You have to add these features to one list and then select all of them:

def SelectFeatures(self):
    layer = self.iface.activeLayer();
    iter = layer.getFeatures();
    selection = []
    for feature in iter:
        selection.append(feature.id())
    layer.setSelectedFeatures(selection)
    self.iface.mapCanvas().setSelectionColor(QColor("yellow"));
    selected_features = layer.selectedFeatures()
    self.iface.mapCanvas().zoomToSelected( layer )
    self.iface.mapCanvas().refresh()
dmh126
  • 6,732
  • 2
  • 21
  • 36
  • i want to select feature one by one not all features. like select feature one zoom it and then select next feature and zoom it. – Keyur Parmar Dec 05 '15 at 09:07
  • for what purpose? Your first script do this but you can't see zooming to the single feature because it is too fast. – dmh126 Dec 05 '15 at 09:12
  • i have to automate the process which can do following thing.
    1. Select first feature.
    2. Zoom it.
    3. Save feature as image.
    4. Select 2nd feature and do the same thing.
    – Keyur Parmar Dec 05 '15 at 09:15
  • Same this is working quite good in console mode but when i create a separate class for achieve same thing it is not working. i am not able to understand why it is working differently? – Keyur Parmar Dec 05 '15 at 09:18
  • so your script will do the job, just at the end of your for loop add lines to save it as image – dmh126 Dec 05 '15 at 09:18
  • in that case it is generating only one image. i want separate image for each feature which is selected and zoomed. – Keyur Parmar Dec 05 '15 at 09:26
  • If it's zooming on each features to print, don't program! Instead just use the built-in atlas ability – ThomasG77 Dec 05 '15 at 15:51
0

I had a similar problem: QGIS waits with repainting until the commands started in the same thread finished. An adoption of this very good recipe How do I prevent Qgis from being detected as "not responding" when running a heavy plugin? did the job. Maybe the following works for you. I included a sleep() to slow down the process.

import time
from PyQt4 import QtCore

class Worker(QtCore.QObject):
    def __init__(self, layer, *args, **kwargs):
        QtCore.QObject.__init__(self, *args, **kwargs)
        self.layer = layer
        self.abort = False

    def run(self):
        try:
            self.feature_count = self.layer.featureCount()
            features = self.layer.getFeatures()
            for feature in features:
                if self.abort is True:
                    self.killed.emit()
                    break
                self.layer.setSelectedFeatures([feature.id()])
                selected_features = self.layer.selectedFeatures()
                self.repaint.emit(feature.id())
                time.sleep(0.5)
        except:
            self.finished.emit(False)
        else:
            self.finished.emit(True)

    def kill(self):
        self.abort = True

    killed = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal(bool)
    repaint = QtCore.pyqtSignal(int)

def repaint(id):
    global layer
    iface.mapCanvas().zoomToSelected(layer)
    try:
        path = 'E:\Test' + str(id) +'.png'
        iface.mapCanvas().saveAsImage(path)
    except:
        print 'ERROR: Writing to file %s failed' % path 
    # more instructions ...
    iface.mapCanvas().refresh()

# get active layer
layer = iface.activeLayer()
iface.mapCanvas().setSelectionColor(QColor("yellow"));

thread = QtCore.QThread()
worker = Worker(layer)
worker.moveToThread(thread)
thread.started.connect(worker.run)
worker.finished.connect(worker.deleteLater)
thread.finished.connect(thread.deleteLater)
worker.finished.connect(thread.quit)
worker.repaint.connect(repaint)
thread.start()
Detlev
  • 4,608
  • 19
  • 26
  • i have tried the code which you have share but whenever i am executing it my qgis is crashed.. – Keyur Parmar Dec 08 '15 at 06:57
  • i have check the crash report it is showing me following details: Dump Summary

    Process Name: qgis-bin.exe : C:\Program Files\QGIS Lyon\bin\qgis-bin.exe Process Architecture: x64 Exception Code: 0xC0000005 Exception Information: The thread tried to read from or write to a virtual address for which it does not have the appropriate access

    – Keyur Parmar Dec 08 '15 at 07:24
  • @KeyurParmar did you already apply changes to the code? I ran it from the Python editor in QGIS 2.8.3 on a Windows 7 64bit machine. Now I have integrated some lines to save the images you are interested in. My QGIS crashed, when writing to file failed. – Detlev Dec 08 '15 at 08:33
  • yes, i have applied the changes to my code. I have not run the code from python editor. I have run the script from my demo plugin. i have Qgis 2.12.0 – Keyur Parmar Dec 08 '15 at 12:38
  • @KeyurParmar are you able to share your plugin code? I currently have no plugin project to test the code in such setting. neumann dot detlev at gmail dot com – Detlev Dec 08 '15 at 17:08
  • sorry, i can't share the plugin code.. but if in case i get the permission i will share it... – Keyur Parmar Dec 09 '15 at 04:12