6. Работа с изображениями
В этой главе вы добавите атрибут picture
к сущности User
и узнаете, как загружать и отображать изображения в пользовательском интерфейсе.
Добавление атрибута-ссылки на файл
Jmix позволяет хранить загруженные файлы вне базы данных в так называемом файловом хранилище (file storage). В простом случае это каталог файловой системы со специальной структурой. Чтобы связать файл, расположенный в файловом хранилище, с сущностью, необходимо создать атрибут типа FileRef
.
Давайте создадим такой атрибут для управления изображением пользователя.
Если ваше приложение запущено, остановите его с помощью кнопки Stop () на главной панели инструментов.
Дважды щелкните на сущности User
в окне инструментов Jmix и выберите атрибут joiningDate
(чтобы добавить новый атрибут после него).
Нажмите на кнопку Add () на панели Attributes. В диалоговом окне New Attribute введите
picture
в поле Name и выберите FileRef
в раскрывающемся списке Type:

Примите предложенное значение (1024) в поле Length. Для атрибута FileRef
это значение определяет длину столбца для хранения ссылки, а не сам файл. Таким образом, значение свойства Length
не ограничивает размер файла.
Нажмите на кнопку OK.
Выберите атрибут picture
и нажмите на кнопку Add 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 () на главной панели инструментов.
Перед запуском приложения Studio сгенерирует Liquibase changelog:

Как вы можете видеть, changelog содержит команду для добавления столбца PICTURE
в таблицу USER_
. Столбец имеет тип VARCHAR(1024)
, потому что ссылка на файл на самом деле является строкой.
Нажмите на кнопку Save and run.
Студия выполнит changelog, затем соберет и запустит приложение.
Откройте http://localhost:8080
в вашем веб-браузере и войдите в приложение с учетными данными администратора (admin
/ admin
).
Раскройте меню Application и нажмите на подпункт Users. Вы увидите колонку Picture на экране User.browse
(прокрутите таблицу вправо):

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

Отображение изображения в форме
В этом разделе вы улучшите экран редактирования, чтобы отобразить загруженное изображение в форме.
Сначала добавьте вторую колонку в компонент form
и переместите в нее компонент fileStorageUpload
:

Затем добавьте компонент 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 и переключитесь на запущенное приложение. Снова откройте экран редактирования пользователя:

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

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

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

Инжектируйте объект 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 и переключитесь на запущенное приложение. Снова откройте экран просмотра пользователя. Вы увидите изображение пользователя в первой колонке таблицы:

Резюме
В этом разделе вы добавили возможность загружать и показывать изображение пользователя.
Вы узнали, что:
-
Загруженные файлы могут храниться в файловом хранилище и связываться с сущностями с использованием атрибутов типа
FileRef
. -
Компонент FileStorageUploadField позволяет загружать файлы, сохранять их в хранилище файлов и ссылаться на атрибут сущности.
-
Компонент Image может отображать изображения, сохраненные в файловом хранилище.
-
Генерируемы колонки можно использовать для отображения изображений в ячейках таблицы.