domingo, 19 de enero de 2020

Clase plantilla con QDialog para usar objetos del tipo QTabWidget como contenedores de QTableWidget en QGIS 3

En el post anterior se propuso una clase plantilla con QDialog para crear objetos del tipo QTabWidget en QGIS 3. En éste se va a usar el primer tab como contenedor de un objeto QTableWidget. La tabla se va a desplegar con n filas y 2 columnas; donde n corresponde al número de capas (vectoriales o ráster) que se encuentran visualizadas en el Map Canvas. La primera columna ('Layer') desplegará el nombre de la capa y la segunda ('Layer type') el tipo de capa (vectorial o ráster). Si el número de capas varía una función conectará automáticamente para dar cuenta de estos cambios.

El código propuesto se expone a continuación:

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from PyQt5.QtCore import Qt

class Dlg(QDialog):

    def __init__(self):
        QDialog.__init__(self)
        self.layout = QGridLayout(self)

        self.tabs = QTabWidget()
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        self.tab3 = QWidget()

        self.tabs.addTab(self.tab1,"Tab1")
        self.tabs.addTab(self.tab2,"Tab2")
        self.tabs.addTab(self.tab3,"Tab3")

        canvas = iface.mapCanvas()
        layers = canvas.layers()

        data = [ [] for i in range(len(layers)) ]
        
        for i, layer in enumerate(layers):
            for j in range(2):
                data[i].append(layer.name())
                if layer.type() == QgsMapLayer.VectorLayer:
                    data[i].append('vector layer')
                    break
                if layer.type() == QgsMapLayer.RasterLayer:
                    data[i].append('raster layer')
                    break

        nb_row = len(data)
        nb_col = 2
        
        self.tab1.layout = QVBoxLayout(self)

        self.table = QTableWidget()
        self.table.setRowCount(nb_row)
        self.table.setColumnCount(nb_col)
        self.table.setHorizontalHeaderLabels(['Layer', 'Layer type'])
        
        for row in range (nb_row):
            for col in range(nb_col):
                item = QTableWidgetItem(str(data[row][col]))
                self.table.setItem(row, col, item)
        
        self.tab1.layout.addWidget(self.table)
        self.tab1.setLayout(self.tab1.layout)
        self.layout.addWidget(self.tabs, 0, 0)
        
        iface.mapCanvas().layersChanged.connect(self.change_layers)

    def change_layers(self):
        
        canvas = iface.mapCanvas()
        layers = canvas.layers()

        data = [ [] for i in range(len(layers)) ]
        
        for i, layer in enumerate(layers):
            for j in range(2):
                data[i].append(layer.name())
                if layer.type() == QgsMapLayer.VectorLayer:
                    data[i].append('vector layer')
                    break
                if layer.type() == QgsMapLayer.RasterLayer:
                    data[i].append('raster layer')
                    break

        nb_row = len(data)
        nb_col = 2

        self.table.setHorizontalHeaderLabels(['Layer', 'Layer type'])
        self.table.setRowCount(nb_row)
        self.table.setColumnCount(nb_col)

        for row in range (nb_row):
            for col in range(nb_col):
                item = QTableWidgetItem(str(data[row][col]))
                self.table.setItem(row, col, item)   

w = Dlg()
w.resize(350,300)
w.setWindowTitle('Example with QTableWidget')
w.setWindowFlags(Qt.WindowStaysOnTopHint)
w.show()

Después de ejecutarlo en la Python Console de QGIS 3 con las capas que se observan en el Map Canvas (dos vectoriales y un ráster):


Como se puede observar en la imagen siguiente, se actualiza automáticamente cuando se desmarca una de las capas vectoriales y la capa ráster.


No hay comentarios: