7.2. 加载和显示图片
我们看看加载、存储和显示员工图片的任务:
员工由
Employee
实体表示。图片文件存储在 FileStorage 中。
Employee
实体包含指向相应FileDescriptor
的链接。Employee
编辑界面显示图片,还支持上传,下载和清除图片。
带有图片文件链接的实体类:
@Table(name = "SAMPLE_EMPLOYEE")
@Entity(name = "sample$Employee")
public class Employee extends StandardEntity {
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "IMAGE_FILE_ID")
protected FileDescriptor imageFile;
public void setImageFile(FileDescriptor imageFile) {
this.imageFile = imageFile;
}
public FileDescriptor getImageFile() {
return imageFile;
}
}
同时加载 Employee
和 FileDescriptor
的视图需要包含 FileDescriptor
的所有本地属性:
<view entity="demo_Employee"
name="employee-edit"
extends="_local">
<property name="imageFile"
view="_local"/>
</view>
Employee
编辑界面 XML 描述的一个片段:
<groupBox caption="Photo" spacing="true"
height="300px" width="300px" expand="image">
<image id="image"
width="100%"
align="MIDDLE_CENTER"
scaleMode="CONTAIN"/>
<hbox align="BOTTOM_LEFT"
spacing="true">
<upload id="uploadField"/>
<button id="downloadImageBtn"
caption="Download"
invoke="onDownloadImageBtnClick"/>
<button id="clearImageBtn"
caption="Clear"
invoke="onClearImageBtnClick"/>
</hbox>
</groupBox>
用于显示、上传和下载图片的组件包含在 groupBox 容器中。容器顶部使用 image 组件显示一张图片,而它的底部从左到右包含上传控件以及下载和清除图片的按钮。因此,界面的这一部分如下所示:
现在,现在我们来看看编辑界面控制器。
import com.company.sales.entity.Employee;
import com.haulmont.cuba.core.entity.FileDescriptor;
import com.haulmont.cuba.core.global.DataManager;
import com.haulmont.cuba.core.global.FileStorageException;
import com.haulmont.cuba.gui.Notifications;
import com.haulmont.cuba.gui.components.Button;
import com.haulmont.cuba.gui.components.FileDescriptorResource;
import com.haulmont.cuba.gui.components.FileUploadField;
import com.haulmont.cuba.gui.components.Image;
import com.haulmont.cuba.gui.export.ExportDisplay;
import com.haulmont.cuba.gui.export.ExportFormat;
import com.haulmont.cuba.gui.model.InstanceContainer;
import com.haulmont.cuba.gui.screen.*;
import com.haulmont.cuba.gui.upload.FileUploadingAPI;
import javax.inject.Inject;
@UiController("sales_Employee.edit")
@UiDescriptor("employee-edit.xml")
@EditedEntityContainer("employeeDc")
@LoadDataBeforeShow
public class EmployeeEdit extends StandardEditor<Employee> {
@Inject
private InstanceContainer<Employee> employeeDc;
@Inject
private Image image;
@Inject
private FileUploadField uploadField;
@Inject
private FileUploadingAPI fileUploadingAPI;
@Inject
private DataManager dataManager;
@Inject
private Notifications notifications;
@Inject
private Button downloadImageBtn;
@Inject
private Button clearImageBtn;
@Subscribe
protected void onInit(InitEvent event) { (1)
uploadField.addFileUploadSucceedListener(uploadSucceedEvent -> {
FileDescriptor fd = uploadField.getFileDescriptor(); (2)
try {
fileUploadingAPI.putFileIntoStorage(uploadField.getFileId(), fd);
} catch (FileStorageException e) {
throw new RuntimeException("Error saving file to FileStorage", e);
}
getEditedEntity().setImageFile(dataManager.commit(fd)); (3)
displayImage(); (4)
});
uploadField.addFileUploadErrorListener(uploadErrorEvent ->
notifications.create()
.withCaption("File upload error")
.show());
employeeDc.addItemPropertyChangeListener(employeeItemPropertyChangeEvent -> { (5)
if ("imageFile".equals(employeeItemPropertyChangeEvent.getProperty()))
updateImageButtons(employeeItemPropertyChangeEvent.getValue() != null);
});
}
@Subscribe
protected void onAfterShow(AfterShowEvent event) { (6)
displayImage();
updateImageButtons(getEditedEntity().getImageFile() != null);
}
public void onDownloadImageBtnClick() { (7)
if (getItem().getImageFile() != null)
exportDisplay.show(getItem().getImageFile(), ExportFormat.OCTET_STREAM);
}
public void onClearImageBtnClick() { (8)
getEditedEntity().setImageFile(null);
displayImage();
}
private void updateImageButtons(boolean enable) {
downloadImageBtn.setEnabled(enable);
clearImageBtn.setEnabled(enable);
}
private void displayImage() { (9)
if (getEditedEntity().getImageFile() != null) {
image.setSource(FileDescriptorResource.class).setFileDescriptor(getEditedEntity().getImageFile());
image.setVisible(true);
} else {
image.setVisible(false);
}
}
}
1 | onInit() 方法首先初始化用于上传新图片的 uploadField 组件。 |
2 | 在成功上传的情况下,从组件获取新的 FileDescriptor 实例,并通过调用 FileUploadingAPI.putFileIntoStorage() 将相应的文件从临时客户端存储发送到 FileStorage 。 |
3 | 之后,通过调用 DataManager.commit() 将 FileDescriptor 保存到数据库中,并将保存的实例分配给 Employee 实体的 imageFile 属性。 |
4 | 然后,调用控制器的 displayImage() 方法显示上传的图片。 |
5 | 之后,将一个监听器添加到包含 Employee 实例的数据容器中。监听器根据文件加载的状态启用或禁用下载和清除按钮。 |
6 | onAfterShow() 方法根据加载的文件是否存在来决定是否显示图片并且更新按钮状态。 |
7 | 点击 downloadImageBtn 按钮时调用 onDownloadImageBtnClick() ,使用 ExportDisplay 接口下载文件。 |
8 | 点击 clearImageBtn 时调用 onClearImageBtnClick() ;它只是清除了 Employee 实体的 imageFile 属性。该文件不会从存储中删除。 |
9 | displayImage() 方法从存储中加载文件并设置 image 组件的内容。 |