5.8.6.1. Displaying Images in a Table Column

To amplify the previous task, let’s add pictures to the table as employees' icons on the Employee browse screen.

The pictures can be displayed in a separate column or inside any existing column. In both cases the Table.ColumnGenerator interface is used.

Below is a fragment of the Employee browse screen XML descriptor:

<groupTable id="employeesTable"
            width="100%"
            height="100%">
    <actions>
        <action id="create"/>
        <action id="edit"/>
        <action id="remove"/>
    </actions>
    <columns>
        <column id="name"/>
    </columns>
    <rows datasource="employeesDs"/>
    <rowsCount/>
    <buttonsPanel id="buttonsPanel"
                  alwaysVisible="true">
        <button id="createBtn"
                action="employeesTable.create"/>
        <button id="editBtn"
                action="employeesTable.edit"/>
        <button id="removeBtn"
                action="employeesTable.remove"/>
    </buttonsPanel>
</groupTable>

To display pictures inline with an employee’s name in the name column, let’s change the standard representation of data in this column. We will use the HBoxLayout container and place the Embedded component into it:

import com.haulmont.cuba.core.entity.FileDescriptor;
import com.haulmont.cuba.gui.components.*;
import com.company.employeeimages.entity.Employee;
import com.haulmont.cuba.gui.export.FileDataProvider;
import com.haulmont.cuba.gui.xml.layout.ComponentsFactory;

import javax.inject.Inject;
import java.util.Map;

public class EmployeeBrowse extends AbstractLookup {

    @Inject
    private ComponentsFactory componentsFactory;

    @Inject
    private GroupTable<Employee> employeesTable;

    @Override
    public void init(Map<String, Object> params) {

        employeesTable.addGeneratedColumn("name", entity -> {
            Embedded embedded = componentsFactory.createComponent(Embedded.class);

            embedded.setType(Embedded.Type.IMAGE);
            embedded.setWidth("40px");
            embedded.setHeight("40px");

            FileDescriptor userImageFile = entity.getImageFile();
            FileDataProvider dataProvider = new FileDataProvider(userImageFile);
            embedded.setSource(userImageFile.getId() + "." + userImageFile.getExtension(), dataProvider);

            Label userLogin = componentsFactory.createComponent(Label.class);
            userLogin.setValue(entity.getName());
            userLogin.setAlignment(Alignment.MIDDLE_LEFT);

            HBoxLayout hBox = componentsFactory.createComponent(HBoxLayout.class);
            hBox.setSpacing(true);
            hBox.add(embedded);
            hBox.add(userLogin);

            return hBox;
        });
    }
}
  • The init() method invokes the addGeneratedColumn() method that takes two parameters: an identifier of the column and an implementation of the Table.ColumnGenerator interface. The latter is used to define the custom representation of data in the name column.

  • Inside this method we create an Embedded component using the ComponentsFactory interface. We set the type of the component (IMAGE) and its size parameters.

  • Then we get the FileDescriptor instance with the picture stored in the File Storage. The link to this picture is stored in the imageFile attribute of the Employee entity. Data provider for FileDescriptor is used to set the source for the Embedded component.

  • We will display the name attribute in the Label component alongside the embedded picture.

  • We will wrap both Embedded and Label components into the HBoxLayout container, and make the addGeneratedColumn() method return this container as the new table cell layout.

image recipe

You can also use a more declarative approach with the generator XML attribute.