Visual Containers

A visual container is a place for storing other objects. It can be thought of as similar to a folder in a file system. Visual containers are also objects, and so they can be nested inside other visual containers.

The Maptek Python SDK class VisualContainer represents visual containers in your project. This class inherits from the Container base class, but you will not typically need to interact with the base class directly.

Container operations

Creating a visual container

A VisualContainer can be created two ways.

Example using Project.new() . This approach is preferred for similarity with creation of other objects. It also conveniently handles the creation of a hierarchy defined by the given path that may not yet exist (e.g. the path /1/2/3/4 would create folders 1, 2, 3, and 4):

from mapteksdk.project import Project
from mapteksdk.data import VisualContainer
proj = Project() # Connect to default project

# Create a VisualContainer under the project root
with proj.new("/my_container", VisualContainer):
    pass

Example using Project.new_visual_container(). This may be less convenient if you need to create several subcontainers and requires the first parameter to be an already existing parent container:

from mapteksdk.project import Project
proj = Project() # Connect to default project

# Create a VisualContainer under the project root
proj.new_visual_container("/","my_container_a")

These objects can be referenced as part of a path for deleting, renaming, editing and creating objects. The root path is / or an empty path. Working with objects under my_container would use the path /my_container/object_name.

The following example demonstrates creation of a tree of containers:

from mapteksdk.project import Project
from mapteksdk.data import VisualContainer
proj = Project() # Connect to default project

for i in range(4):
    for j in range(2):
        for k in range(2):
            with proj.new("/i_{}/j_{}/k_{}".format(i, j, k), VisualContainer):
                pass


Note:  You do not need to create containers for new objects before creating the objects. If a path is used for a new object that would nest it in containers that don't yet exist, the SDK will manage their creation.

Reading the children of a container

Since 1.5

The contents of a container can be read by opening the container for reading and then using VisualContainer.names(), VisualContainer.ids(), or VisualContainer.items() functions, which return lists of the names of the children, the object IDs of the children, and the name and object ID of the children. respectively.

This is an alternative to Project.get_children(container).

Querying number of children

Since 1.5

The number of children can be queried by calling len() on the opened object.

Querying name of a child

Since 1.5

The name of a given object can be queried by ID using the VisualContainer.name_of_object() function. An object can appear in more than one container and can have more than one name.

Querying the object ID of child by name

Since 1.5

The object ID that is associated with the given name in the container can be queried by calling the VisualContainer.get() function with the name of the object. If the name is not used within the container then the null object ID (i.e. if you test it for the truth value, it will be False).

Checking if name or ID is in a container

Since 1.5

To check if there is a child of a given name or object ID within the container, you can use the in keyword on the container in a conditional expression. For example, if cad in root_container or if cad_object in root_container.

Clear the contents of a container

Since 1.5

The VisualContainer.clear() function on a container removes all the children from a container and any child object that is not in another container will be deleted.

It does not clear the object attributes of the container, only the objects that are within it.

Adding objects to a container

Since 1.5

Objects can be added to a container through the VisualContainer.append() and VisualContainer.insert() functions. They both require the child to be expressed as a tuple of its name and object ID.

The VisualContainer.append() function adds the child object at the end of the container, whereas VisualContainer.insert() allows you to insert it at a position within the container, where an index of 0 will ensure it’s put at the start of the container.

Removing children from a container

Since 1.5

A child can be removed from the container either by name using the VisualContainer.remove() function or by using the del keyword (e.g. del container["child_name"]).

It is possible to remove a child by object ID using the VisualContainer.remove_object() function, which will remove only the first child that matches. This is because the same object can be in a container more than once under different names.

Replacing object with a name with different object

Since 1.5

You can replace an object with a given name with a different object within the container by using the VisualContainer.rename() function. This is different from simply calling VisualContainer.remove() then VisualContainer.append() because it will preserve the position. This is useful in the situation where you want to make a substitution.

Renaming items in a container

A limitation of Project.rename_object() is that it only allows the caller to rename one item at a time. You can call it multiple times in a loop, however this is suboptimal (especially when there are more than about a dozen objects in the container) because it will open the container for edit, rename the object, close it and repeat. This process will often be seen by the user of the script in the application’s project explorer as they will see things change one at a time.

In the following example, the items will be renamed object 1, object 2, object 3 using VisualContainer.rename(). This might not seem useful in itself, but it illustrates the principle, which can be extended to rename objects to something more meaningful, such as the value of an object attribute.

# For each selected container, rename the children to be of the form
# object 1, object 2, object 3, ... object N.
from mapteksdk.data import VisualContainer
from mapteksdk.project import Project

if __name__ == '__main__':
    with Project() as project:    
        containers = [selected_object
                      for selected_object in project.get_selected()
                      if selected_object.is_a(VisualContainer)]

        for container_id in containers:
            with project.edit(container_id) as container:
                # Take a copy of the container names as otherwise the names
                # would change while looping over them.
                original_names = container.names()[:]
                for number, original_name in enumerate(original_names,
                                                       start=1):
                    container.rename(original_name, f'object {number}')

Other container examples

Other examples involving containers are presented in the topic on projects, including the following: