Suite

Rendu QgsRasterLayer sans ajouter à la légende


J'essaie de rendre un certain nombre d'objets QgsRasterLayer liés les uns aux autres (ce sont des tuiles de type glissant). Idéalement, je voudrais qu'un élément de la légende puisse changer sa position (c'est-à-dire se déplacer au-dessus ou au-dessous d'autres éléments de la légende) et ajouter une boîte de dialogue d'actions/propriétés personnalisées, mais que le rendu réel des tuiles soit effectué par QgsRasterLayer.

Ma première approche était d'essayer de sous-classer QgsPluginLayer et de remplacer ledessiner()méthode pour appelerQgsRasterLayer.draw()pour chacun de mes rasters chargés. Cela ne fait rien, même si des couches sont ajoutées auRegistre QgsMapLayer.

def draw(self, renderContext): pour rasterlayer dans self.loadedlayers.values(): rasterlayer.draw(renderContext)

Ma deuxième approche était de créer un groupe dans la légende qui est en quelque sorte caché. Je peux ajouter le calque à l'arborescence des calques en utilisant

mygroup = QgsProject.instance().layerTreeRoot().addGroup("mygroup") pour rasterlayer dans self.loadedlayers.values() : mygroup.addMapLayer(rasterlayer)

mais il ne semble pas possible de cacher ce groupe à l'utilisateur. À partir de Afficher uniquement certaines couches dans la légende QGIS ? il ne semble pas qu'il y ait d'alternative. J'ai l'impression qu'il existe une solution facile à cela que je ne vois pas.

EDIT : j'ai essayé de créer unQgsMapLayerRendererobjet qui restitue le calque en une image à l'aide d'unQgsMapRenderer, et bien que cela fonctionne occasionnellement, il produit souvent une sortie qui semble avoir des éléments de l'écran actuel dans l'image de sortie (peut-être quelque chose à voir avec l'utilisation d'un QgsMapRenderer() alors qu'un est déjà invoqué sur le thread actuel ?). Dans monQgsPluginLayerJ'ai:

def createMapRenderer(self, context): return MultiRasterRenderer(self, context)

Et monQgsMapLayerRendererest-ce (inclut une sortie de débogage):

class MultiRasterRenderer(QgsMapLayerRenderer): def __init__(self, layer, context): QgsMapLayerRenderer.__init__(self, layer.id()) self.layer = layer self.context = context def render(self): fout = open("/ Users/dewey/Desktop/outputdump.txt", "w") rendererContext = self.context si len(self.layer.loadedlayers) > 0 : img = QImage(QSize(self.context.painter().device(). width (), self.context.painter ().device (). .setLayerSet([layer.id() pour le calque dans self.layer.loadedlayers.values()]) render.setProjectionsEnabled(True) render.setDestinationCrs(rendererContext.coordinateTransform().destCRS()) fout.write("Etendue du contexte : " + rendererContext.extent().toString() + "
") si render.setExtent(rendererContext.extent()): render.setOutputSize(img.size(), img.logicalDpiX()) render.render( peintre) painter.end() img.save("/Users/dewey/Desktop/outp ut.jpg">

Après beaucoup de débogage, j'ai finalement trouvé une solution assez simple. Lors de la création d'un nouveauQImage()il semble, leQImage()n'est pas vide, et donc la solution à ce problème était d'appelerQImage.fill(Qt.transparent)avant de rendre la carte à l'image. Il n'était pas nécessaire d'invoquer unQgsMapLayerRendererparce qu'il n'y avait pas de rendu multi-thread… tout se passait à partir du thread de rendu. Le finalQgsPluginLayerle code est le suivant :

class QOSMTileLayer(QgsPluginLayer): LAYER_TYPE = "QOSM_LAYER_TYPE" def __init__(self, layertype, layerName): QgsPluginLayer.__init__(self, QOSMTileLayer.LAYER_TYPE, layerName) self.layertype = {layertype set = self.loadedtiles } self.setValid(True) def refrshlayers(self):… def draw(self, rendererContext): if len(self.loadedlayers) > 0: render = QgsMapRenderer() render.setLayerSet(self.loadedlayers.values()) render .setProjectionsEnabled(True) render.setDestinationCrs(rendererContext.coordinateTransform().destCRS()) render.setExtent(rendererContext.extent()) img = QImage(QSize(rendererContext.painter().device().width(), rendererContext .painter ().device (). setRenderHint(QPainter.Antialiasing) render.setOutputSize(img.size(), img.logicalDpiX()) render.render(painter) painter.end() rendererContext.painter( ).drawImage(0, 0, img) else : #pas de tuiles. passer retour Vrai


Voir la vidéo: 7 règles de football que tu IGNORES! (Octobre 2021).