jueves, 26 de octubre de 2017

Cómo conectar una QComboBox para actualizar adecuadamente las capas mediante PyQGIS en un plugin

La actualización automática de las capas (vectoriales o ráster) en objetos del tipo Combo Box ("persiana desplegable") puede realizarse con objetos del tipo QgsMapLayerComboBox en PyQGIS. Sin embargo, siempre existe aquel que quiere hacerlo todo desde cero empleando los precursores Qt denominados QComboBox.

En este caso, cada vez que se detecta una situación o un cambio en el número de capas en el Map Canvas, el registro o en la interface de leyendas debería conectarse al slot (función) para que la QComboBox se actualice debidamente.

En el link aquí señalado se tiene una referencia que presenta un procedimiento completo para un plugin funcional. Sin embargo, se programa la QComboBox directamente en el método 'run' del plugin y eso trae un efecto no deseado porque ésta se llena de manera irregular (repitiendo capas) con sólo abrir y cerrar el plugin.

Para que funcione adecuadamente la QComboBox parte del código debería estar en '__init__' para llenarla con las capas que se encuentren en ese momento cargadas en la Map View de QGIS. En run lo que debería estar programado es un método que al detectar cualquier cambio en el número de capas (aumento o disminución) se conecte automáticamente a una función para que las actualice adecuadamente.

El método es 'groupRelationsChanged' de QgsLegendInterface para conectar al slot. El código parcial del plugin que se encuentra a continuación señala donde se deberían colocar las instrucciones para que funcione como se espera.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
.
   .
   .
    def __init__(self, iface):
   .
   .
   .
        self.dlg.comboBox.clear()
        layers = self.iface.legendInterface().layers()
        layer_list = [ layer.name() for layer in layers ]
        self.dlg.comboBox.addItems(layer_list)
   .
   .
   .
    def change_layers(self):
        self.dlg.comboBox.clear()
        layers = self.iface.legendInterface().layers()
        layer_list = [ layer.name() for layer in layers ]
        self.dlg.comboBox.addItems(layer_list)

    def run(self):
        """Run method that performs all the real work"""
        self.iface.legendInterface().groupRelationsChanged.connect(self.change_layers)
        # show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed
        if result:
            # Do something useful here - delete the line containing pass and
            # substitute with you

Las imágenes a continuación señalan diferentes situaciones que pueden presentarse.

1) El plugin se ejecuta con dos capas previamente cargadas:


2) Se añaden tres capas simultáneamente:


y la Combo Box las registra adecuadamente:


3) Se remueven cuatro capas de manera simúltanea:


y nuevamente el comportamiento de la Combo Box es el esperado.


No hay comentarios: