5

On my map canvas I have various point objects spread through several layers. My plan is to 'animate' those objects by a loop from start to a predefined resolution.

By now I'm just testing the algorithm with the vertical positions of the existing objects and an exportCanvas function which saves the canvas as a single image for each step.

Because this method isn't very handy I want to have the output of the loop directly to the canvas - delayed by e.g. 0.5 seconds per step.

result to be
Above is an example of the merged jpg-files to a gif

The problem is that my loop doesn't work very well at all and freezes my QGIS for the whole process time (+delay).
I know that I need some kind of hyperthreading or callback from QGIS to my plugin but at this point I have no clue how to transfer this idea to useful code

Down below: the code so far

# Animation: Button clicked
def btnAnimationClicked(self):       
    rate = 24

    # Werte zum Färben der xyz
    for i in range(0,rate,1):
        self.caller(i, self.callback)

# Animation: Caller
def caller(self, val, func):
    func(val)

# Animation: Callback
def callback(self, i):
    yhi = 5699049523 + 400000 
    ylo = 5696625163
    delta = yhi - ylo
    rate = 24
    ste = delta / rate 

    ubound = ylo + (ste * (i+1))
    lbound = ylo + (ste * i)

    values = (
        ('hi', ubound + 1, yhi, 'red'),
        ('is', lbound, ubound, 'green'),
        ('lo', ylo, lbound - 1, 'yellow'),
    )           
    # HaKasten abgestuft färben     
    for layer in QgsMapLayerRegistry.instance().mapLayers().values():
        if layer.name()[0:9] == "xyz_______":    
            ranges = []
            for label, lower, upper, color in values:
                symbol = QgsSymbolV2.defaultSymbol(layer.geometryType())
                symbol.setColor(QColor(color))
                rng = QgsRendererRangeV2(lower, upper, symbol, label)
                ranges.append(rng)
            attribut = 'y'
            renderer = QgsGraduatedSymbolRendererV2(attribut, ranges)
            layer.setRendererV2(renderer)    
    for layer in qgis.utils.iface.mapCanvas().layers():
        layer.triggerRepaint()
    #time.sleep(0.5) # optional
    self.exportCanvas() 

1 Answer 1

3

Solved.
With use of the modoule thread (>Python 3.0 _thread) you are able to start new threads inside your programm code.

import thread

# Animation: Button clicked
def btnAnimationClicked(self):            
    thread.start_new_thread(self.caller,())

# Animation: Caller
def caller(self):
    for i in range(0,24,1):
        self.callback(i)

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.