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 Views () на панели Attributes.
В появившемся диалоговом окне будут показаны все экраны, на которых отображается сущность User
. Выберите экран User.detail
и нажмите OK.
Studio создаст компонент pictureField
в форме экрана User.detail
:
<formLayout id="form" dataContainer="userDc">
...
<fileStorageUploadField id="pictureField" property="picture"/>
</formLayout>
Нажмите на кнопку Debug () на главной панели инструментов.
Перед запуском приложения Studio сгенерирует Liquibase changelog:

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

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

Теперь компонент fileStorageUpload
расположен не непосредственно в formLayout
, который определяет контейнер данных для своих вложенных компонентов. Поэтому необходимо установить свойство dataContainer
в fileStorageUpload
явно:

Затем добавьте компонент image
и установите следующие атрибуты:
<details summaryText="Picture">
<hbox>
<fileStorageUploadField id="pictureField" dataContainer="userDc" property="picture"/>
<image id="image" property="picture" dataContainer="userDc" height="10em" width="10em"
classNames="user-picture"/>
</hbox>
</details>
-
dataContainer="userDc" property="picture"
связывают компонентimage
с атрибутомpicture
сущностиUser
. -
classNames="user-picture"
указывает класс CSS, который задается далее.
Откройте файл onboarding.css
из раздела User Interface → Themes и задайте класс user-picture
:

Свойство object-fit: contain
гарантирует, что изображение заполнит всю выделенную область, но сохранит пропорции.
.user-picture {
object-fit: contain;
}
Нажмите Ctrl/Cmd+S и переключитесь на запущенное приложение. Обновите экран деталей пользователя и попробуйте загрузить изображение:

Отображение изображения в таблице
Давайте создадим колонку для отображения изображения в таблице экрана User.list
.
Откройте user-list-view.xml
и добавьте следующую колонку в usersDataGrid
:
<columns resizable="true">
<column key="picture" sortable="false" flexGrow="0" resizable="false"/>
Добавьте следующие поля в класс UserListView
:
@ViewComponent
private DataGrid<User> usersDataGrid;
@Autowired
private UiComponents uiComponents;
@Autowired
private FileStorage fileStorage;
Вы можете использовать кнопку Inject в верхней панели действий редактора, чтобы инжектировать зависимости в контроллеры экрана и бины Spring. |
Выберите колонку picture
в иерархии, переключитесь на вкладку Handlers инспектора и создайте обработчик `renderer. Реализуйте его следующим образом:
@Supply(to = "usersDataGrid.picture", subject = "renderer")
private Renderer<User> usersDataGridPictureRenderer() {
return new ComponentRenderer<>(user -> { (1)
FileRef fileRef = user.getPicture();
if (fileRef != null) {
Image image = uiComponents.create(Image.class); (2)
image.setWidth("30px");
image.setHeight("30px");
StreamResource streamResource = new StreamResource(
fileRef.getFileName(),
() -> fileStorage.openStream(fileRef));
image.setSrc(streamResource); (3)
image.setClassName("user-picture");
return image; (4)
} else {
return null;
}
});
}
1 | Метод возвращает объект Renderer , создающий UI-компонент, отображаемый в ячейках колонки. Рендерер принимает экземпляр сущности данной строки. |
2 | Экземпляр компонента Image создается с помощью фабрики компонентов UiComponents . |
3 | Компонент изображения получает свое содержимое из файлового хранилища по ссылке, хранящейся в атрибуте picture сущности User . |
4 | Рендерер возвращает визуальный компонент, который будет отображаться в ячейках колонки. |
Нажмите Ctrl/Cmd+S и переключитесь на запущенное приложение. Обновите экран списка пользователей. Вы увидите изображение пользователя в первой колонке таблицы:

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