Suite

Comment éviter un plantage de QGIS lorsqu'il est ajouté une couche de symboles dans un symbole ?

Comment éviter un plantage de QGIS lorsqu'il est ajouté une couche de symboles dans un symbole ?


Lorsque j'exécute le code suivant sur la console Python de QGIS avec une couche vectorielle linéaire :

symbol1 = QgsLineSymbolV2.createSimple({'penstyle':'solid', 'color':'black', 'width':'3' }) symbol2 = QgsLineSymbolV2.createSimple({'penstyle':'dash', 'color' :'white', 'width':'0', 'customdash':'8;4', 'use_custom_dash': '1' }) route = iface.activeLayer() renderer = route.rendererV2() type1 = symbol1. type() type2 = symbol2.type() print "Le calque de symboles est-il compatible ?", symbol1.isSymbolLayerCompatible(type2) #Créer des calques de symboles symbol_layer1 = symbol1.symbolLayer(0) symbol_layer2 = symbol2.symbolLayer(0) #Ajouter le calque de symboles 2 à symbol1 (maintenant avec deux couches de symboles) symbol1.appendSymbolLayer(symbol_layer2) renderer.setSymbol(symbol1) route.triggerRepaint() iface.legendInterface().refreshLayerSymbology(route)

J'ai obtenu le résultat suivant :

indiquant que le symbole2 (QgsLineSymbolV2 classe), car la couche de symboles (symbol_layer2 appartient à QgsLineSymbolLayerV2 class), il s'ajoutait correctement à symbol1. Cependant, lorsque ce code est exécuté à nouveau, QGIS se bloque et ferme toutes les fenêtres. Ce comportement n'apparaît pas si le symbole n'a qu'une seule couche de symboles ; lorsqu'il est commenté, à la première exécution, la ligne avec cette instruction :

symbol1.appendSymbolLayer(symbol_layer2)).

Comment puis-je empêcher le deuxième crash de QGIS lorsque j'utilise un symbole avec 2 couches de symboles ou plus ?


Raison

Lorsque vous créez un symbole, il est propriétaire de ses calques. Lorsque vous ajoutez une couche à un symbole existant, il devient propriétaire de la couche ajoutée. La propriété signifie qu'il est libre de le supprimer quand il le souhaite.

Dans votre exemple, les deux symboles assument la propriété de symbol_layer2 (symbol2 car il a créé symbol_layer2, symbol1 car symbol_layer2 y a été ajouté).

Maintenant, lorsque vous exécutez le code une deuxième fois, symbol2 est remplacé par un nouveau, donc python supprime symbol2 et symbol2 supprime symbol_layer2 car il en a la propriété.

Lorsque vous définissez ultérieurement un nouveau symbole sur le moteur de rendu, il supprime l'ancien symbole (que vous avez défini lors de la première exécution du code) car il n'est plus utilisé. Le (ancien) symbol1 est supprimé et avec lui symbol_layer2 dont symbol1 devient également propriétaire. Mais - pas de chance - cela a déjà été supprimé par symbol2. Et supprimer deux fois la même chose entraîne un plantage…

Solution

Clonez la couche de symboles pour que les deux aient leur propre copie sur laquelle travailler

symbol1.appendSymbolLayer(symbol_layer2.clone())

Ou retirez le symbollayer de symbol2

symbol_layer2 = symbol2.takeSymbolLayer(0)

Ou créez directement une couche de symboles au lieu d'en emprunter une construite par un symbole.

Est-ce un bug ?

Non, il s'agit d'un comportement attendu.

Il existe plusieurs possibilités de provoquer des plantages avec du code python. Cependant, il y a place à amélioration dans la documentation de l'API. Cela sera bientôt changé.