6. Работа с изображениями

В этой главе вы добавите атрибут picture к сущности User и узнаете, как загружать и отображать изображения в пользовательском интерфейсе.

Добавление атрибута-ссылки на файл

Jmix позволяет хранить загруженные файлы вне базы данных в так называемом файловом хранилище (file storage). В простом случае это каталог файловой системы со специальной структурой. Чтобы связать файл, расположенный в файловом хранилище, с сущностью, необходимо создать атрибут типа FileRef.

Давайте создадим такой атрибут для управления изображением пользователя.

Если ваше приложение запущено, остановите его с помощью кнопки Stop (suspend) на главной панели инструментов.

Дважды щелкните на сущности User в окне инструментов Jmix и выберите атрибут joiningDate (чтобы добавить новый атрибут после него).

Нажмите на кнопку Add (add) на панели Attributes. В диалоговом окне New Attribute введите picture в поле Name и выберите FileRef в раскрывающемся списке Type:

attribute 2

Примите предложенное значение (1024) в поле Length. Для атрибута FileRef это значение определяет длину столбца для хранения ссылки, а не сам файл. Таким образом, значение свойства Length не ограничивает размер файла.

Нажмите на кнопку OK.

Выберите атрибут picture и нажмите на кнопку Add to Screens (add attribute to screens) на панели Attributes.

В появившемся диалоговом окне будут показаны все экраны, на которых отображается сущность User. Выберите оба экрана User.edit и User.browse и нажмите OK.

Studio создаст колонку picture в таблице пользователей usersTable на экране User.browse:

<groupTable id="usersTable" dataContainer="usersDc" ...>
    ...
    <columns>
        ...
        <column id="picture"/>
    </columns>

и компонент pictureField в форме экрана User.edit:

<form id="form" dataContainer="userDc">
    <column ...>
        ...
        <fileStorageUpload id="pictureField" property="picture"/>
    </column>

Нажмите на кнопку Debug (start debugger) на главной панели инструментов.

Перед запуском приложения Studio сгенерирует Liquibase changelog:

run app 1

Как вы можете видеть, changelog содержит команду для добавления столбца PICTURE в таблицу USER_. Столбец имеет тип VARCHAR(1024), потому что ссылка на файл на самом деле является строкой.

Нажмите на кнопку Save and run.

Студия выполнит changelog, затем соберет и запустит приложение.

Откройте http://localhost:8080 в вашем веб-браузере и войдите в приложение с учетными данными администратора (admin / admin).

Раскройте меню Application и нажмите на подпункт Users. Вы увидите колонку Picture на экране User.browse (прокрутите таблицу вправо):

run app 2

Выделите пользователя в таблице и нажмите на кнопку Edit. UI-компонент для загрузки изображения показан в нижней части формы:

run app 3

Отображение изображения в форме

В этом разделе вы улучшите экран редактирования, чтобы отобразить загруженное изображение в форме.

Сначала добавьте вторую колонку в компонент form и переместите в нее компонент fileStorageUpload:

form 1

Затем добавьте компонент image ниже компонента fileStorageUpload. Укажите следующие атрибуты:

<form id="form" dataContainer="userDc">
    ...
    <column>
        <fileStorageUpload id="pictureField" property="picture"/>
        <image id="image" property="picture"
               scaleMode="CONTAIN"
               rowspan="10" caption=""
               height="200" width="200"/>
    </column>
</form>
  • property="picture" связывает компонент image с атрибутом picture сущности User.

  • scaleMode="CONTAIN" гарантирует, что изображение заполнит всю выделенную область, но сохранит пропорции.

  • rowspan="10" позволяет компоненту заполнить до 10 строк формы вместо 1. Таким образом, изображение будет занимать все доступное пространство справа.

  • caption="" удаляет заголовок по умолчанию, определенный для атрибута сущности.

Нажмите Ctrl/Cmd+S и переключитесь на запущенное приложение. Снова откройте экран редактирования пользователя:

form 2

Если вы загружаете изображение из файла, имя файла будет отображаться полем fileStorageUpload, а изображение будет отображаться компонентом image:

form 3

Отображение изображения в таблице

Если вы закроете экран редактирования после загрузки изображения, вы увидите, что в колонке таблицы отображается только название загруженного файла:

table 1

Давайте переместим колонку picture в первую позицию и создадим для нее обработчик columnGenerator:

table 2

Инжектируйте объект UiComponents в класс контроллера:

@Autowired
private UiComponents uiComponents;
Вы можете использовать кнопку Inject на верхней панели действий редактора, чтобы инжектировать зависимости в контроллеры экрана и бины Spring.

Реализуйте метод обработчика:

@Install(to = "usersTable.picture", subject = "columnGenerator") (1)
private Component usersTablePictureColumnGenerator(User user) { (2)
    if (user.getPicture() != null) {
        Image image = uiComponents.create(Image.class); (3)
        image.setScaleMode(Image.ScaleMode.CONTAIN);
        image.setSource(FileStorageResource.class)
                .setFileReference(user.getPicture()); (4)
        image.setWidth("30px");
        image.setHeight("30px");
        return image; (5)
    } else {
        return null;
    }
}
1 Аннотация @Install указывает, что метод является делегатом: UI компонент (в данном случае таблица) вызывает его на каком-то этапе своего жизненного цикла.
2 Этот конкретный делегат (генератор колонок) получает экземпляр сущности, который отображается в строке таблицы в качестве аргумента.
3 Экземпляр компонента Image создается с помощью фабрики компонентов UiComponents.
4 Компонент изображения получает свое содержимое из файлового хранилища по ссылке, хранящейся в атрибуте picture сущности User.
5 Делегат генератора колонок возвращает визуальный компонент, который будет отображаться в ячейках колонки.

Нажмите Ctrl/Cmd+S и переключитесь на запущенное приложение. Снова откройте экран просмотра пользователя. Вы увидите изображение пользователя в первой колонке таблицы:

table 3

Резюме

В этом разделе вы добавили возможность загружать и показывать изображение пользователя.

Вы узнали, что:

  • Загруженные файлы могут храниться в файловом хранилище и связываться с сущностями с использованием атрибутов типа FileRef.

  • Компонент FileStorageUploadField позволяет загружать файлы, сохранять их в хранилище файлов и ссылаться на атрибут сущности.

  • Компонент Image может отображать изображения, сохраненные в файловом хранилище.

  • Генерируемы колонки можно использовать для отображения изображений в ячейках таблицы.