You are here:GeoTux»Geo-Blogs»Librerías para Geomática»Tabla de contenido (leyenda) para aplicaciones basadas en PyQGIS

Estadísticas

Invitados: 22
Usuarios registrados: 3126
Usuarios en línea:
-
Registrados hoy:
-

Registro

Redifusión (RSS)

Blogs y Noticias:
Recibe las actualizaciones en Geo-Noticias y Geo-Blogs

Recibir por e-mail
Recibir Geo-Noticias y Geo-Blogs por e-mail

¿Qué es esto?

En Twitter

Martes 18 de Enero de 2011 06:01

Tabla de contenido (leyenda) para aplicaciones basadas en PyQGIS

Written by  German Carrillo
Rate this item
(4 votes)

QGIS provee varias utilidades para desarrollar con Python. Sin embargo, si se quiere construir una aplicación independiente con PyQGIS se deben crear algunos controles como la tabla de contenido, un control imprescindible en una aplicación SIG. A continuación comparto una.

Nota: For the English version click here.

 

He creado un control para aplicaciones basadas en PyQGIS que es una versión muy simplificada con relación a la tabla de contenido de QGIS. La principal diferencia es que la mía no maneja grupos de capas. El control está basado también en la leyenda de OpenOceanMap, escrita por Aaron Racicot, pero en lugar de trabajar con controles QCheckBox, utiliza QTreeWidgetItem para representar cada capa del mapa.

 

Así es como luce:

Tabla de contenido para PyQGIS

 

Qué permite esta tabla de contenido?

  • Obtener un listado ordenado de capas.
  • Mover capas hacia arriba o hacia abajo en el listado para modificar el orden de despliegue en el mapa.
  • Hacer una capa visible o no visible.
  • Visualizar/cambiar la simbología de la capa (se da un ejemplo muy básico cambiando únicamente el color de la capa).
  • Cambiar algunas propiedades de la capa.
  • Cargar/Guardar archivos de estilo de QGIS (.qml).
  • Remover capas del mapa.
  • Integrar el mapa con otras herramientas que actúan sobre las capas cargadas (por ejemplo, Mostrar/Ocultar/Remover todas las capas).

 

Cuál es la licencia de esta tabla de contenido?

La licencia es GNU GPL v.2.

 

Como agrego la tabla de contenido a mi aplicación de PyQGIS?

Para incluir la tabla de contenido en una aplicación de PyQGIS se deben seguir estos pasos:

 

1. Descargar este archivo ZIP y extraer su contenido en la carpeta de la aplicación. El archivo contiene el archivo legend.py, el cual contiene la definición de la tabla de contenido, varias imágenes (íconos) para representar los tipos de capas y las opciones del menú, y finalmente, un diálogo que es usado para definir algunas propiedades de las capas.

Los íconos pueden obtenerse desde este enlace, puesto que son del proyecto QGIS.

 

2. Importar la clase Legend.

En la clase principal de la aplicación, la cual hereda de QMainWindow, se debe importar la clase Legend class desde el archivo legend.py, así:

 

 from legend import Legend

 

3. Agregar el método CreateLegendWidget.

Incluir el método CreateLegendWidget en la clase principal de la aplicación para agregar el dock widget a la interfaz de usuario y asociar el canvas a la tabla de contenido. El método es este:

 

  def createLegendWidget( self ):
""" Create the map legend widget and associate to the canvas """
self.legend = Legend( self )
self.legend.setCanvas( self.canvas )
self.legend.setObjectName( "theMapLegend" )

self.LegendDock = QDockWidget( "Layers", self )
self.LegendDock.setObjectName( "legend" )
self.LegendDock.setAllowedAreas( Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea )
self.LegendDock.setWidget( self.legend )
self.LegendDock.setContentsMargins ( 9, 9, 9, 9 )
self.addDockWidget( Qt.LeftDockWidgetArea, self.LegendDock )

 

En el método __init__ de la clase principal de la aplicación, llamar el método recién creado:

 

    self.createLegendWidget()   # Create the legend widget

 

4. Compilar/Importar un archivo de recursos para incluir los íconos.

La tabla de contenido incluye algunos íconos, para cargarlos, se debe compilar el archivo resources.qrc con el siguiente comando:

 

   $ pyrcc4 resources.qrc -o resources_rc.py 

 

El archivo legend.py contiene una referencia al archivo generado. Sin embargo, si se tiene un archivo de recursos previo, es posible agregar las imágenes de la carpeta imgs a un nuevo prefijo, por ejemplo, "legend". Si se quiere elegir otro prefijo se debe modificar la variable resource_prefix del archivo legend.py.

 

 resources_prefix = ":/legend/imgs/" 

 

5. Permitir que la tabla de contenido administre las capas cargadas y removidas para evitar fallos de segmentación.

La aplicación debe tener un método para cargar capas, pero ahora que se busca incluir una tabla de contenido, es esta la que manejará esta funcionalidad. La tabla de contenido tiene un SLOT para manejar el conjunto de capas (layer set) en el momento en que se carga, se mueve o se remueve una capa. Lo que se debe hacer es llamar los métodos apropiados (bien sea addMapLayer o removeMapLayer) de la instancia del singleton QgsMapLayerRegistry, pero no emplear el método setLayerSet del canvas, puesto que la tabla de contenido lo hará. Entonces, se deben comentar o borrar los llamados al método setLayerSet.

 

    QgsMapLayerRegistry.instance().addMapLayer( layer );
#self.canvas.setLayerSet( self.layers )

 

6. Cargar el diálogo de propiedades.

Para permitir que el usuario defina algunas propiedades de las capas se debe compilar el archivo dlgLayerProperties.ui, el cual provee un diálogo básico.

 

   $ pyuic4 dlgLayerProperties.ui -o dlgLayerProperties_ui.py  

 

Diálogo de propiedades de la capa

 

7. (Opcional) Habilitar herramientas

La tabla de contenido emite una SIGNAL que permite habilitar o deshabilitar herramientas de la aplicación, según el tipo de la capa activa sea ráster o vector. La SIGNAL es llamada activeLayerChanged y si se quiere usar, se debe escribir algo como esto en la clase principal de la aplicación:

 

      self.connect( self.legend, SIGNAL( "activeLayerChanged" ),
self.enableTools )

... # Probably more code

def enableTools( self ):
if not self.legend.activeLayer():
# Disable some general tools
else:
# Enable some general tools
layerType = self.legend.activeLayer().layer().type()
if layerType == 0: # Vector Layer
# Enable vector tools and disable others
elif layerType == 1: # Raster Layer
# Enable raster tools and disable others

 

8. (Opcional) Usar algunos métodos para exponer funcionalidades a otras herramientas o plugins:

 

  • Iterar sobre las capas del mapa:
    for layer in self.legend.layers:
...

 

  • Mostrar u ocultar todas las capas del mapa:
    def showAllLayers( self ):
self.legend.setStatusForAllLayers( True )

 

  • Obtener la capa activa (para plugins):
    return self.legend.activeLayer()

 

  • Actualizar la simbología de la capa (para plugins):
    self.legend.refreshLayerSymbology( layer )

 

  • Remover capas por Id (para plugins):
    self.legend.removeLayers( layerIds )

 

Eso es todo!

 

Last modified on Miércoles 28 de Septiembre de 2011 21:07

Comentarios  

 
0 # Traducción al rusotuxman 25-02-2011 22:52
El equipo de GIS-LAB ha publicado hoy un artí­culo en ruso basado en este post. Puede ser consultado en este enlace:
http://gis-lab.info/qa/qgis-legend.html (gis-lab.info/qa/qgis-legend.html)
Responder | Responder con una citación | Citar
 
 
0 # GIS analystpierre sylvain 30-05-2012 15:45
Hello,

I'm developping a Python application and i'm using your devs. Great job!
I get some trouble with vectorLayerSymb ology method:it seems that the renderer is not convenient.

Line: renderer = layer.renderer()
AttributeError: 'NoneType' object has no attribute 'symbols'
So I have to use rendererV2, and rendererV2 doesn't support getPointSymbolA sImage method...
Do you have any idea to fix it?
Thanks
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 07-06-2012 21:10
Hi,

glad you find it useful.

The problem you have now is related to this legend's lack of support for symbology-ng (new generation) in QGIS.

You can replace the functions of this file [1] (in legend.py) to have single symbology-ng working, but not categorized nor graduated I guess.

Most of the functionality in this legend is adapted from [2] (in C++), so if you can deal with a bit of C++ code and adapt it to Python, please let me know, we could work enabling this legend to support symbology-ng. In that case I would set up a SVN repository for the code.

Regards,

Tuxman
---------
[1] http://downloads.tuxfamily.org/tuxgis/geoblogs/pyqgis_toc/functions_to_replace.py
[2] https://raw.github.com/qgis/Quantum-GIS/master/src/app/legend/qgslegendlayer.cpp
Responder | Responder con una citación | Citar
 
 
0 # GIS analystpierre sylvain 13-06-2012 13:32
You’re right !
During last days I’ve found a solution looking into cpp code.
Now it works. But I think code is not realy clean (I’m a Python newby !) The next step for me : legend group !
The first question is : create a new class Legendgroup like LegendItem or as a subclass of legendItem ?
I look at C++ and try to "translate" into Python.
But I got a problem to give a type to QTreeWidgetItem s, I don't know the way to write such lines:
QgsLegendItem *litem = dynamic_cast( item );
QgsLegendGroup *group = dynamic_cast( item );
QgsLegendLayer *layer = dynamic_cast( item );

Regards
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 13-06-2012 17:31
Hi Pierre,

I recall I did something like that this way:

object.__class__ = AnotherClass

Please consider sharing your work. :roll:

Regards,

Tuxman
Responder | Responder con una citación | Citar
 
 
-1 # GIS analystpierre sylvain 14-02-2013 14:18
Hello,
I'm back!

Work is going on, and I have much more question specialy if I compare legend.py to QGis legend behaviour:
In QGis when you check on or off a layer, only these one is redraw not all other.
That’s not the legend.py behaviour now.
What should be the best way to do this inside legend.py?

PS: I didn't forget your proposal to share my dev, but at this moment it is embeded inside my app, so hard to share, but…
Responder | Responder con una citación | Citar
 
 
0 # Add two layers to canvasBarbara Duarte 07-01-2016 14:32
Hello.
Congratulations for your plugin. It is very useful for me.
But I have a doubt related with more than one layer added and their visualization in map canvas. I had one layer and it is every ok (I didn't use all the properties of the plugin). But when I add a new layer, this opens in my map canvas and the first one disappear. So in the legend I have two layers and only one in map canvas. I just want you to explain which funtion deals with this and if I have to do something else in my main code.

Hope that you helps me. Thank you.

Best regards.
Responder | Responder con una citación | Citar
 
 
+1 # Re:tuxman 07-01-2016 16:12
Hi Barbara,

thanks! You don't need this component anymore, because QGIS (thanks to Martin Dobias) now gives us a Layer Tree View, have a look at: http://bit.ly/1GJlVkN and tell me if there is something unclear to you.

Regards,

Tuxman
Responder | Responder con una citación | Citar
 
 
0 # Add two layers to canvas - actionsBarbara Duarte 15-01-2016 15:14
Hi tuxman,

thank you so much for the answer. I try and I get it!! Now my layers are in correct order. But I miss other widgets that I would like to have in my application. For example, the possibility of zoom extent and to remove the layer (by clicking with the right button of the mouse in the layer, as actions). This actions belongs to legend.py but know I am not able to do that. Can you help please?
Tahnk you.

Beste regards,
Lia Duarte
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 22-01-2016 13:52
Hi Barbara,

please have a look at the documentation of the QgsLayerTreeVie w [1], specifically at the bullet point "Display of context menu."

You'll find there indications on how to implement your own context menu, as well as an example. Please give it a try; if I remember well, when I gave it a try it didn't work for me. If that's the case also for you, we could file a ticket reporting the issue.

If you have success, please tell me how you achieved it :)

Regards,

Tuxman
----
[1] http://www.lutraconsulting.co.uk/blog/2015/01/30/qgis-layer-tree-api-part-3/
Responder | Responder con una citación | Citar
 
 
0 # Add two layers to canvasBarbara Duarte 22-01-2016 22:36
Hi tuxman,

It works!!! :) Thank you so much, it was very very useful this help.

Thank you for all the help.
Best regards,
Lia Duarte
Responder | Responder con una citación | Citar
 
 
0 # Re:tuxman 22-01-2016 23:35
Glad you found it useful, Barbara.
BTW, we publish tips like this in our Twitter account: twitter.com/GeoTux2 Follow us there!

Regards,

Tuxman
Responder | Responder con una citación | Citar
 

Escribir un comentario


Código de seguridad
Refescar

 

¿Dónde nos leen?

Últimos comentarios