9

I'm struggling to understand how to manage print layouts using python for QGIS. For example, I am starting with Zero exisiting print layouts in my layout manager. I create a new print layout and add a label to it with this code:

project = QgsProject.instance()                                  
manager = project.layoutManager()
layout = QgsPrintLayout(project)
layout.initializeDefaults()                         
layoutName = "PrintLayout"
layout.setName(layoutName)
manager.addLayout(layout)  

layout.setName(layoutName)
manager.addLayout(layout)

title = QgsLayoutItemLabel(layout)
title.setText("Title Here")
title.setFont(QFont("Arial", 28))
title.adjustSizeToText()
layout.addLayoutItem(title)
title.attemptMove(QgsLayoutPoint(10, 4, QgsUnitTypes.LayoutMillimeters))

This is simple enough, it creates a new print layout called "PrintLayout" and it looks like this:
enter image description here

But if I run this code another time, I start getting problems. If I run exactly the same code, except I change the following line:

title.setText("Title There")

I get the following result. As you can see, "Title There" and "Title Here" are now overlaid on top of each other. This isn't good. enter image description here

So I started thinking if an existing print layout exists with the same name, maybe I can delete that layout and create a new one. So I try the following code:

project = QgsProject.instance()                                  
manager = project.layoutManager()
layout = QgsPrintLayout(project)
layout.initializeDefaults()                         
layoutName = "PrintLayout"
layout.setName(layoutName)
manager.addLayout(layout)  

layouts_list = manager.printLayouts()

for layout in layouts_list:
    print(layout.name())

for layout in layouts_list:
    if layout.name() == layoutName:
        layouts_list.remove(layout)

for layout in layouts_list:
    print(layout.name())

title = QgsLayoutItemLabel(layout)
title.setText("Title There")
title.setFont(QFont("Arial", 28))
title.adjustSizeToText()
layout.addLayoutItem(title)
title.attemptMove(QgsLayoutPoint(10, 4, QgsUnitTypes.LayoutMillimeters))

Notice, I created a variable "layouts_list" which stores my layouts and for loop to check the names of existing layouts, if the name equals the new layout I want to create, I remove before creating a new one. Also, I print the layout names from the layout manager before and after checking the layout names.

However, it seems the .remove() method doesn't actually remove a layout from the layout manager.

J.Monticolo suggested I try the .removeLayout() method. So I modified my for loop like this:

for layout in layouts_list:
    if layout.name() == layoutName:
        manager.removeLayout(layout)

This does actually remove the layout from the layout manager. But I'm met with this error: enter image description here

This makes sense. I did delete the layout. But a new layout is not created. They should be as my remaining code makes a new layout and adds a title to it.

Why does this error message stop the code, before creating a new layout?

Here is the final code all together:

project = QgsProject.instance()                                  
manager = project.layoutManager()
layout = QgsPrintLayout(project)
layout.initializeDefaults()                         
layoutName = "PrintLayout"
layout.setName(layoutName)
manager.addLayout(layout)  

layouts_list = manager.printLayouts()

for layout in layouts_list:
    if layout.name() == layoutName:
        manager.removeLayout(layout)

layout.setName(layoutName)
manager.addLayout(layout)

title = QgsLayoutItemLabel(layout)
title.setText("Title There")
title.setFont(QFont("Arial", 28))
title.adjustSizeToText()
layout.addLayoutItem(title)
title.attemptMove(QgsLayoutPoint(10, 4, QgsUnitTypes.LayoutMillimeters))
4
  • 1
    For the remove code, have you tried the QgsLayoutManager.removeLayout method ? Commented Feb 7, 2019 at 16:24
  • Can you post more of your script? What you have here is correct, so it's something in between the two code sections or in how they are being called which is incorrect.
    – ndawson
    Commented Feb 7, 2019 at 21:49
  • @J.Monticolo Thank you for the comment. I did try the .removeLayout method. This removed the print layout, but makes an error before I create a new layout Commented Feb 8, 2019 at 16:20
  • @ndawson I revised the post to include all the steps and also posted an answer below Commented Feb 8, 2019 at 21:00

2 Answers 2

11

You attempt to set a name to a deleted object.

You need to create a new object :

[...]
for layout in layouts_list:
    if layout.name() == layoutName:
        manager.removeLayout(layout)

layout = QgsPrintLayout(project)
layout.setName(layoutName)
[...]
0
4

I will answer my own question, which is a follow up to J.Monticolo's answer.

Start by creating a print layout as I did earlier, you can use the following code to do that:

project = QgsProject.instance()                                  
manager = project.layoutManager()
layout = QgsPrintLayout(project)                   
layoutName = "PrintLayout" 

Now create a list of print manager layouts. You can loop through these to check and see if the layout name is equal to your layoutName. If so, remove the layout:

layouts_list = manager.printLayouts()

for layout in layouts_list:
    if layout.name() == layoutName:
        manager.removeLayout(layout)

Now that you have deleted the existing print layout (if needed), you can create a new one. Make sure to create a new layout object and .initializeDefaults() to create your map canvas:

layout = QgsPrintLayout(project)
layout.initializeDefaults()                 #create default map canvas
layout.setName(layoutName)
manager.addLayout(layout)

Now you can continue adding other stuff to the map canvas like a map, legend, etc.

Here is what it looks like all together:

project = QgsProject.instance()                                  
manager = project.layoutManager()
layout = QgsPrintLayout(project)                   
layoutName = "PrintLayout" 

layouts_list = manager.printLayouts()

for layout in layouts_list:
    if layout.name() == layoutName:
        manager.removeLayout(layout)

layout = QgsPrintLayout(project)
layout.initializeDefaults()                 #create default map canvas
layout.setName(layoutName)
manager.addLayout(layout)

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.