5

With PyQGIS 3, I defined a comboBox to list layers from a QGIS project. I want to use the selected one to execute a treatment. I tried comboBox.currentData() class but it doesn't seem to be the good way.

How can I handle the selected layer from the comboBox as a vector layer ?

Maybe with comboBox.itemData() or comboBox.currentIndex() classes ?

# ComboBox
layers = QgsProject.instance().layerTreeRoot().children()    
self.dlg.comboBox.addItems([layer.name() for layer in layers])
# Not the good way
selectedLayer = self.dlg.comboBox.currentData()

# Vector Layer
mySelectedLayer = QgsVectorLayer(selectedLayer, 'polygon', 'ogr')
0

3 Answers 3

7

There is a recommended way to do this: Use the built-in custom widget called QgsMapLayerComboBox.

You can find it in Qt Designer under the QGIS custom widgets group.

enter image description here

Once you open the dialog in QGIS, the combo box will be filled with all the layers in the QgsProject. QgsMapLayerComboBox offers handy methods for you to filter such list (see the docs).

When you're ready to read and use the selected layer, e.g., after the users accepts the dialog, you can access the selected layer in this way:

layer = self.dlg.mMapLayerComboBox.currentLayer()  # Real QgsMapLayer object

And that's it!


Annex: Why is your code failing?

Using a normal Qt ComboBox, you have several options to access a layer selected in the combo box. The best way is to use my_combo_box.addItem(layer_name, layer_object) instead of using my_combo_box.addItems(...) for filling the combo box.

In this way you can then get direct access to the selected layer using

layer = self.dlg.comboBox.currentData()
2
  • 3
    Yes, it's much better to use QGIS widgets instead of creating your own widgets. Less code to maintain and you will have icons already.
    – etrimaille
    Nov 11, 2019 at 13:11
  • QGIS custom widgets is a better way, you're right. It's really easier to handle my selected layer.
    – GeoGyro
    Nov 11, 2019 at 13:35
4

You can access the current text in your QComboBox via

lyr_name = my_combo.currentText()

and the layer via

the_layer = QgsProject.instance().mapLayersByName(lyr_name)[0]

mapLayersByName() method returns a list because QGIS can handle various layers of the same name. Thus, I often use [0] because in most of my cases the layer names are unique.

Reference: https://qgis.org/api/classQgsProject.html#a935efacacb942a15afe19728233e35c3

1
  • Ok with my_combo.currentText()
    – GeoGyro
    Nov 11, 2019 at 13:32
4

I recommend the answer of Germán Carrillo. I'm adding another way to get these custom widgets, just in case if it's not listed in QtDesigner, in the left menu.

You can use a normal QComboBox in QtDesigner. Then right-clic on it and choose Promote to....

Then you can add custom widgets:

Name of base class: `QComboBox`
Name of promoted class: `QgsMapLayerComboBox`
Header: `qgis.gui`
1
  • Great, thank you for this trick.
    – GeoGyro
    Nov 11, 2019 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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