3

I'm using the plugin builder to develop a plugin QGIS. I want the fields of the selected layer in combobox_1 to appear in combobox_5and fields of the selected layer in comboBox_2 to appear in comboBox_3 and comboBox_4.

I am new to python and PyQGIS. I do not have the methods defined in initGUI. How can I achieve this?

def initGui(self):
    """Create the menu entries and toolbar icons inside the QGIS GUI."""

    icon_path = ':/plugins/TheWorkflow/icon.png'
    self.add_action(
        icon_path,
        text=self.tr(u'The Workflow'),
        callback=self.run,
        parent=self.iface.mainWindow())

def unload(self):
    """Removes the plugin menu item and icon from QGIS GUI."""
    for action in self.actions:
        self.iface.removePluginVectorMenu(
            self.tr(u'&The Workflow'),
            action)
        self.iface.removeToolBarIcon(action)
    # remove the toolbar
    del self.toolbar

def run(self):
    """Run method that performs all the real work"""
    # 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

enter image description here

2
  • Did you manage to input the code from this answer inside your def run(self): function in your mainPlugin.py file?
    – Joseph
    Commented Oct 21, 2016 at 10:41
  • Put the Python Console on and then run your plugin. It should tell you if there's any errors when it loads or when you try to select a layer from the combobox.
    – Joseph
    Commented Oct 21, 2016 at 11:16

3 Answers 3

5

Just a small note that we should use QGIS builtin combobox:

These QGIS objects manage to fill the combobox automatically with layers or to display fields according to a specific layer. And they provide a nice UI with some small icons: enter image description here

1
  • Yup, those are indeed much more convenient to use :)
    – Joseph
    Commented Oct 24, 2016 at 10:40
2

You can try replacing your def run(self): function in your script for the one below which should do something you want:

def run(self):
    """Run method that performs all the real work"""
    # show the dialog
    self.dlg.show()

    # Get all loaded layers in the interface
    layers = self.iface.legendInterface().layers()
    # Create an empty list which we can populate
    layer_list = []
    # For every item (which we call "layer") in all loaded layers
    for layer in layers:
        # Add it to the list
        layer_list.append(layer.name())
    # Clear comboBox (useful so we don't create duplicate items in list)
    self.dlg.comboBox.clear()
    # Add all items in list to comboBox
    self.dlg.comboBox.addItems(layer_list)
    # Clear comboBox_2
    self.dlg.comboBox_2.clear()
    # Add all items in list to comboBox_2
    self.dlg.comboBox_2.addItems(layer_list)

    def layer_field():
        # Identify selected layer by its index
        selectedLayerIndex = self.dlg.comboBox.currentIndex()
        selectedLayer = layers[selectedLayerIndex]
        # Identify fields of the selected layer
        fields = selectedLayer.pendingFields()
        # Get field names of the fields
        fieldnames = [field.name() for field in fields]
        # Clear comboBox_5
        self.dlg.comboBox_5.clear()
        # Add field names to comboBox_5
        self.dlg.comboBox_5.addItems(fieldnames)

    def table_field():
        # Same comments as above
        selectedLayerIndex = self.dlg.comboBox_2.currentIndex()
        selectedLayer = layers[selectedLayerIndex]
        fields = selectedLayer.pendingFields()
        fieldnames = [field.name() for field in fields]
        self.dlg.comboBox_3.clear()            
        self.dlg.comboBox_3.addItems(fieldnames)
        self.dlg.comboBox_4.clear()
        self.dlg.comboBox_4.addItems(fieldnames)

    # When changing layer in comboBox, run the function "layer_field()"
    # to refresh the field names in the associated comboBoxes
    self.dlg.comboBox.currentIndexChanged.connect(layer_field)
    self.dlg.comboBox_2.currentIndexChanged.connect(table_field)
4
  • thank you so much! Please, how can I come back to you for future reference?
    – robson
    Commented Oct 21, 2016 at 13:45
  • @robson - Most welcome but I would very, very strongly suggest you read through the PyQGIS Cookbook as it teaches you step-by-step how to use Python in QGIS. You can also just use your favourite search engine and type "pyqgis" followed by whatever it is you are stuck at and you will get more resources. If you are still having problems then you can always post your question here at GIS:SE but you are greatly encouraged to try first.
    – Joseph
    Commented Oct 21, 2016 at 13:50
  • @robson - Lastly, I am self-taught and still learning from all the resources and the amazing people here at GIS:SE so I am definitely not an expert in this :). I will edit my post and insert some comments in the code which might be useful.
    – Joseph
    Commented Oct 21, 2016 at 13:52
  • 1
    I will follow your suggestions and hope to soon contribute with other users of GIS SE :)
    – robson
    Commented Oct 21, 2016 at 13:56
1

according to @Joseph's answer, if you want to populate your combobox with fields of vector layers, since raster layers does not have any fields of attribute you may get the error: AttributeError: 'QgsRasterLayer' object has no attribute 'fields'.

so for avoiding that you must equal your Layers with Only vector layers, like this:

layers = [layer for layer in iface.legendInterface().layers() if layer.type() == QgsMapLayer.VectorLayer]

instead of:

layers = iface.legendInterface().layers() 

good luck...

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.