I have some shapefiles with distribution (range) maps for some species of butterflies. I want to load them, give each map a title, and export each map as a PDF with the name in accordance with the title. So far the code I have works (loads the .shp, create a .pdf with each .shp, and name the file accordingly). What is not working is the title of the map: it doesn't work but no error message is delivered. Any suggestion?

#load the shapefiles

repr_list = [] 

for layer in glob.glob("*.shp"):     
    vlayer = QgsVectorLayer(os.path.join(outdir,layer), layer, "ogr")
    if not QgsProject.instance().mapLayersByName(layer): 

#define the list of layers
layerlist = QgsProject.instance().mapLayers().values()

#define an index for repr_list (I will take the names from that list, as if I index layerlist I get TypeError: 'QgsVectorLayer' object is not subscriptable)
i = 0 

for layer in layerlist:
    QgsProject.instance().layerTreeRoot().findLayer(layer.id()).setItemVisibilityChecked(True) #turn the layer on
    projectInstance = QgsProject.instance()
    layoutmanager = projectInstance.layoutManager()
    layout = layoutmanager.layoutByName("Butterflies") #Layout name: go Project > Layout manager > Butterflies (if it's not already present, add it) > Add new map
    exporter = QgsLayoutExporter(layout)
    #add map title
    map_label = QgsLayoutItemLabel(layout)    
    #set what the text will be
    map_label.setText(repr_list[i][:-14]) # [:-14] removes unnecessary file endings
    #add map_label to your layout
    outname = outdir + repr_list[i][:-14]  + ".pdf"
    exporter.exportToPdf(outname, QgsLayoutExporter.PdfExportSettings())
    QgsProject.instance().layerTreeRoot().findLayer(layer.id()).setItemVisibilityChecked(False) #turn the layer off
    i = i + 1

I am using QGIS version 3.22.6 on Windows 10.

1 Answer 1


You have to specify position and size of the label.

map_label.setText("foo bar")

# Position
point = QgsLayoutPoint(10, 10, QgsUnitTypes.LayoutMillimeters)

# Size
size = QgsLayoutSize(100, 20, QgsUnitTypes.LayoutMillimeters)


enter image description here

Since you use a for loop, you need to remove the previous label. Therefore, add layout.removeLayoutItem(map_label) to the end of for loop.

for layer in layerlist:

    # previous code lines   

    i = i + 1
  • Thanks. This shows the labels, but 1) only the 1st label is fine, then the 2nd label is added above the 1st one - is there a way to remove the label before (similar to turning the layer off)? 2) a label is created in the Object window of the Layout manager every time I run the script (so if I re-run the script, in the end, there are a lot of duplicated labels).
    – LT17
    Commented Dec 20, 2022 at 12:12
  • How many labels are there on the page? I mean how many you need. just one? Commented Dec 20, 2022 at 12:17
  • There are 14 layers, and I need only one label (that would be repr_list[i][:-14]) for each layer in layerslist.
    – LT17
    Commented Dec 20, 2022 at 12:57
  • Need to remove the previous label after exporting the layout. Please check my edit. Commented Dec 20, 2022 at 13:13
  • Yes, exactly, that works. Thanks a lot!
    – LT17
    Commented Dec 20, 2022 at 13:25

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.