我的 TableView 显示图片的地址但不是实际图片
My TableView displays the address of the picture but not the actual picture
嘿,我正在尝试保存名称为 "Avatar" 的对象,然后检索该对象并显示其图片 "image"。我得到了这个结果:
我的头像Class:
@Entity
@Table(name="avatar")
public class Avatar implements java.io.Serializable {
@Id
private Integer avatarId;
@Column(name = "image")
private byte[] image;
//getters and setters
我如何保存对象:
session.getTransaction().begin();
File file = new File("PicturePath");
byte[] bFile = new byte[(int) file.length()];
try {
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
Avatar avatar = new Avatar();
avatar.setAvatarId(1);
avatar.setImage(bFile);
session.save(avatar);
session.getTransaction().commit();
正在从 Avatar 中检索数据 Table:
public List<Avatar> avatarList(){
session.getTransaction().begin();
List<Avatar> avatar = session.createQuery("from Avatar").list();
session.getTransaction().commit();
return avatar;
}
控制器:
@FXML
public TableView<Avatar> produits;
@FXML
public void initialize(){
Task<ObservableList<Avatar>> task = new Task<ObservableList<Avatar>>() {
@Override
protected ObservableList<Avatar> call() throws Exception {
return FXCollections.observableArrayList(CategorieTrait.getInstance().avatarList());
}
};
produits.itemsProperty().bind(task.valueProperty());
new Thread(task).start();
}
我的 FXML 文件:
<TableView style="-fx-backround-color:#33d9b2;" fx:id="produits" prefWidth="900" prefHeight="600">
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
</columnResizePolicy>
<columns>
<TableColumn text="Picture" style="-fx-backround-color:#33d9b2">
<cellValueFactory>
<PropertyValueFactory property="image"/>
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
我期待在表格视图中显示实际图片。
您看不到图像的原因是,尽管您正确地为 TableView
提供了图像的字节,但您没有告诉它如何渲染它们。您需要的是将字节数组呈现为 ImageView
的自定义 TableCell
。所以我会做以下事情:
首先在你的fxml文件中的TableColumn
中添加一个id属性:
<TableColumn fx:id="imageColumn" text="Picture" style="-fx-backround-color:#33d9b2">
<cellValueFactory>
<PropertyValueFactory property="image"/>
</cellValueFactory>
</TableColumn>
然后在你的 Controller 中引用它并添加一个 CellFactory 到它:
@FXML
public TableView<Avatar> produits;
@FXML
public TableColumn<Avatar, byte[]> imageColumn;
@FXML
public void initialize() {
...
imageColumn.setCellFactory(param -> new TableCell<Avatar, byte[]>() {
private ImageView imageView = new ImageView();
@Override
protected void updateItem(byte[] item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setGraphic(null);
} else {
imageView.setImage(getImageFromBytes(item));
setGraphic(imageView);
}
this.setItem(item);
}
});
...
}
CellFactory
为您的每个 Avatar 项目创建一个 table 单元格,该单元格的 updateItem()
方法将字节转换为 Image
呈现为 ImageView
(如果单元格不为空)。
这是一种将字节数组转换为 JavaFX Image:
的方法
private Image getImageFromBytes(byte[] imgBytes) {
try {
ByteArrayInputStream inputStream = new ByteArrayInputStream(imgBytes);
BufferedImage bufferedImage = ImageIO.read(inputStream);
return SwingFXUtils.toFXImage(bufferedImage, null);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
重要说明:我会避免从 updateItem()
内部调用 getImageFromBytes()
方法,尤其是对于具有大量记录的 TableView。为了简单起见,我只是这样做了。您可能想事先转换图像,并可能将它们存储在地图或其他东西中。
编辑: 将 updateItem()
方法更改为每次调用时不创建新的 ImageView
。
嘿,我正在尝试保存名称为 "Avatar" 的对象,然后检索该对象并显示其图片 "image"。我得到了这个结果:
我的头像Class:
@Entity
@Table(name="avatar")
public class Avatar implements java.io.Serializable {
@Id
private Integer avatarId;
@Column(name = "image")
private byte[] image;
//getters and setters
我如何保存对象:
session.getTransaction().begin();
File file = new File("PicturePath");
byte[] bFile = new byte[(int) file.length()];
try {
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
Avatar avatar = new Avatar();
avatar.setAvatarId(1);
avatar.setImage(bFile);
session.save(avatar);
session.getTransaction().commit();
正在从 Avatar 中检索数据 Table:
public List<Avatar> avatarList(){
session.getTransaction().begin();
List<Avatar> avatar = session.createQuery("from Avatar").list();
session.getTransaction().commit();
return avatar;
}
控制器:
@FXML
public TableView<Avatar> produits;
@FXML
public void initialize(){
Task<ObservableList<Avatar>> task = new Task<ObservableList<Avatar>>() {
@Override
protected ObservableList<Avatar> call() throws Exception {
return FXCollections.observableArrayList(CategorieTrait.getInstance().avatarList());
}
};
produits.itemsProperty().bind(task.valueProperty());
new Thread(task).start();
}
我的 FXML 文件:
<TableView style="-fx-backround-color:#33d9b2;" fx:id="produits" prefWidth="900" prefHeight="600">
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
</columnResizePolicy>
<columns>
<TableColumn text="Picture" style="-fx-backround-color:#33d9b2">
<cellValueFactory>
<PropertyValueFactory property="image"/>
</cellValueFactory>
</TableColumn>
</columns>
</TableView>
我期待在表格视图中显示实际图片。
您看不到图像的原因是,尽管您正确地为 TableView
提供了图像的字节,但您没有告诉它如何渲染它们。您需要的是将字节数组呈现为 ImageView
的自定义 TableCell
。所以我会做以下事情:
首先在你的fxml文件中的TableColumn
中添加一个id属性:
<TableColumn fx:id="imageColumn" text="Picture" style="-fx-backround-color:#33d9b2">
<cellValueFactory>
<PropertyValueFactory property="image"/>
</cellValueFactory>
</TableColumn>
然后在你的 Controller 中引用它并添加一个 CellFactory 到它:
@FXML
public TableView<Avatar> produits;
@FXML
public TableColumn<Avatar, byte[]> imageColumn;
@FXML
public void initialize() {
...
imageColumn.setCellFactory(param -> new TableCell<Avatar, byte[]>() {
private ImageView imageView = new ImageView();
@Override
protected void updateItem(byte[] item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setGraphic(null);
} else {
imageView.setImage(getImageFromBytes(item));
setGraphic(imageView);
}
this.setItem(item);
}
});
...
}
CellFactory
为您的每个 Avatar 项目创建一个 table 单元格,该单元格的 updateItem()
方法将字节转换为 Image
呈现为 ImageView
(如果单元格不为空)。
这是一种将字节数组转换为 JavaFX Image:
private Image getImageFromBytes(byte[] imgBytes) {
try {
ByteArrayInputStream inputStream = new ByteArrayInputStream(imgBytes);
BufferedImage bufferedImage = ImageIO.read(inputStream);
return SwingFXUtils.toFXImage(bufferedImage, null);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
重要说明:我会避免从 updateItem()
内部调用 getImageFromBytes()
方法,尤其是对于具有大量记录的 TableView。为了简单起见,我只是这样做了。您可能想事先转换图像,并可能将它们存储在地图或其他东西中。
编辑: 将 updateItem()
方法更改为每次调用时不创建新的 ImageView
。