[GIS] ComboBox Field not updating when layer is selected

pyqgispyqtqgis-plugins

I try to develop my plugin. The problem is that when the layer is selected in upper comboBox (QgsMapsLayerComboBox), in lower two boxes (Latitude, Longitude: usual ComboBoxes) shall appear fields correspoding with selected layers.

enter image description here

The problem is, that when I switch the layer in upper field, I can only choose the fields which are from the other layer…

enter image description here

On this picture, the fields "ID", "LONGITUDE", "LATITUDE" belongs to previously selected layer "coordinates" visible on 1st photo.

Here's my code of def_run of my plugin:

def run(self):

    self.dlg.layerCombo2.clear()
    self.dlg.layerCombo3.clear()

    layers = self.iface.legendInterface().layers()
    layer_list = []
    for layer in layers:
        layer_list.append(layer.name())
    self.dlg.layerCombo1.addItems(layer_list)
    self.dlg.layerCombo1.setFilters(QgsMapLayerProxyModel.PointLayer)

    def field_select():
        self.dlg.layerCombo2.clear()
        self.dlg.layerCombo3.clear()
        selectedLayerIndex = self.dlg.layerCombo1.currentIndex()
        selectedLayer = layers[selectedLayerIndex]
        fields = [field.name() for field in selectedLayer.pendingFields()]
        self.dlg.layerCombo2.addItems(fields)
        self.dlg.layerCombo3.addItems(fields)

    # This connects the function to the layer combobox when changed
    self.dlg.layerCombo1.currentIndexChanged.connect(field_select)
    self.dlg.show()

`

Best Answer

This is the code snippet in my Test Plugin:

.
.
.
from qgis.gui import QgsMapLayerComboBox, QgsMapLayerProxyModel, QgsFieldComboBox
.
.
.

    def add_action(
.
.
.
        self.wcbL = QgsMapLayerComboBox(self.dlg)
        self.wcbL.move(250, 80)
        self.wcbL.setFixedWidth(203)
        self.wcbL.setFilters(QgsMapLayerProxyModel.PointLayer)

        self.wcbF = QgsFieldComboBox(self.dlg)
        self.wcbF.move(250, 120)
        self.wcbF.setFixedWidth(203)

        return action
.
.
.
    def select_layer_fields(self, vlayer):
        self.wcbF.setLayer(vlayer)
        field = self.wcbF.setLayer(vlayer)

    def run(self):
        """Run method that performs all the real work"""
        vlayer = self.wcbL.currentLayer()
        self.wcbF.setLayer(vlayer)
        self.wcbL.layerChanged.connect(self.select_layer_fields)

        # 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 your code.
            pass

I tried it out with two point layers; as it can be observed at following images.

With layer points_test (only one field):

enter image description here

When random_points layer was selected in QgsMapLayerComboBox, fields in this layer were automatically also selected in QgsFieldComboBox object (following image):

enter image description here

Plugin works as expected.

Editing Note 1:

Following image also contains a QgsMapLayerComboBox object added directly with QtDesigner. Its name is mMapLayerComboBox.

enter image description here

Editing Note 2:

When Combo Boxes are adding by using QtDesigner following code works as expected:

.
.
.
    def change_layers2(self):                                           #new function
        self.dlg.mMapLayerComboBox.clear()
        layers = self.iface.legendInterface().layers()
        layer_list = [ layer.name() for layer in layers ]
        self.dlg.mMapLayerComboBox.addItems(layer_list)

    def select_layer_fields2(self, vlayer):                              #new function
        self.dlg.mFieldComboBox.setLayer(vlayer)
        field = self.dlg.mFieldComboBox.setLayer(vlayer)

    def run(self):
        """Run method that performs all the real work"""
        vlayer = self.wcbL.currentLayer()
        self.wcbF.setLayer(vlayer)
        self.wcbL.layerChanged.connect(self.select_layer_fields)

        vlayer = self.dlg.mMapLayerComboBox.currentLayer()                           #new line
        self.dlg.mFieldComboBox.setLayer(vlayer)                                     #new line
        self.dlg.mMapLayerComboBox.layerChanged.connect(self.select_layer_fields2)   #new line
.
.
.

It can be observed at following image:

enter image description here