1

I use a QgsMapLayerComboBox nested with a QgsFieldComboBox in Qt. The problem is that I can select only one field with the field combobox and I need to select several fields.

self.dlg.mMapLayerComboBox_2.layerChanged['QgsMapLayer*'].connect(self.dlg.mFieldComboBox_2.setLayer)

That's why instead of using a Combobox I would like to replace the FieldComboBox by a QListWidget.

How can I fill a QListWidget by the list of field of the Layer selected by MapLayerCombobox?

1 Answer 1

3

Here is an example which you can run in an editor in the Python console. This should provide you with an example of adding items to the list widget from a list of field names from the current layer in the map layer combo box and updating the fields whenever the layer is changed; allowing multiple selections with:

self.fld_list.setSelectionMode(QListWidget.ExtendedSelection)

clearing the selection, and retrieving the QgsField objects from the list widget selected items. My example creates a dictionary of field names and field objects by calling the text() method on the QListWidgetItem objects returned by the selectedItems() method.

class Dlg(QDialog):

    def __init__(self):
        QDialog.__init__(self)
        self.layout = QGridLayout(self)
        self.cb_layer = QgsMapLayerComboBox()
        self.cb_layer.setFilters(QgsMapLayerProxyModel.VectorLayer)
        self.cb_layer.layerChanged.connect(self.layer_changed)
        self.fld_list = QListWidget(self)
        self.fld_list.setSelectionMode(QListWidget.ExtendedSelection)
        self.fld_list.addItems([f.name() for f in self.cb_layer.currentLayer().fields()])
        self.btn1 = QPushButton('Clear selection', self)
        self.btn1.clicked.connect(lambda: self.fld_list.clearSelection())
        self.te1 = QTextEdit(self)
        self.btn2 = QPushButton('Retrieve selected fields', self)
        self.btn2.clicked.connect(self.get_selection)
        self.layout.addWidget(self.cb_layer, 0, 0)
        self.layout.addWidget(self.fld_list, 1, 0)
        self.layout.addWidget(self.btn1, 2, 0)
        self.layout.addWidget(self.te1, 3, 0)
        self.layout.addWidget(self.btn2, 4, 0)

    def layer_changed(self, layer):
        self.fld_list.clear()
        flds = [f.name() for f in layer.fields()]
        self.fld_list.addItems(flds)

    def get_selection(self):
        inds = [i.text() for i in self.fld_list.selectedItems()]
        flds = {}
        for i in inds:
            flds[i] = [f for f in self.cb_layer.currentLayer().fields() if f.name() == i][0]
        self.te1.setText(str(flds))


W = Dlg()
W.show()

Result:

enter image description here

enter image description here

2
  • this solution is really perfect ! it helps to understand how it works, thanks so much
    – zlikotp
    Commented Dec 29, 2019 at 10:00
  • You're most welcome!
    – Ben W
    Commented Dec 29, 2019 at 10:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.