Java My TableView显示图片的地址,但不显示实际图片

Java My TableView显示图片的地址,但不显示实际图片,java,hibernate,javafx,java-io,Java,Hibernate,Javafx,Java Io,嘿,我正在尝试保存一个名为“阿凡达”的对象,然后检索该对象并显示其图片“图像”。我得到了这个结果: 我的化身类: @Entity @Table(name="avatar") public class Avatar implements java.io.Serializable { @Id private Integer avatarId; @Column(name = "image") private byte[] image; //getters and s

嘿,我正在尝试保存一个名为“阿凡达”的对象,然后检索该对象并显示其图片“图像”。我得到了这个结果:

我的化身类:

@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();
从化身表中检索数据:

public List<Avatar> avatarList(){
        session.getTransaction().begin();
        List<Avatar> avatar = session.createQuery("from Avatar").list();
        session.getTransaction().commit();
        return avatar;
    }
公开列表化身列表(){
session.getTransaction().begin();
List avatar=session.createQuery(“来自avatar”).List();
session.getTransaction().commit();
返回化身;
}
控制器:

 @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产品;
@FXML
公共无效初始化(){
任务=新任务(){
@凌驾
受保护的ObservableList调用()引发异常{
返回FXCollections.observearraylist(CategorieTrait.getInstance().avatarList());
}
};
produits.itemsProperty().bind(task.valueProperty());
新线程(任务).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中。

无法看到图像的原因是,尽管您正确地为
tableview提供了图像字节,但您没有告诉它如何渲染它们。您需要的是一个定制的
TableCell
,它将字节数组呈现为
ImageView
。因此,我将做以下工作:

首先在fxml文件的
表格列中添加id属性:

<TableColumn fx:id="imageColumn" text="Picture" style="-fx-backround-color:#33d9b2">
    <cellValueFactory>
        <PropertyValueFactory property="image"/>
    </cellValueFactory>
</TableColumn>
重要提示:我会避免从
updateItem()
内部调用
getImageFromBytes()
方法,特别是对于包含大量记录的TableView。我这么做只是为了简单。您可能希望事先转换图像,并将其存储在地图或其他东西中


Edit:更改了
updateItem()
方法,使其在每次调用时不创建新的
ImageView

如果要显示图片,请将图片提供给tableview,而不是字节数组。以这个问题为例,我不确定你用来读取文件的逻辑在所有情况下都能起作用。该方法会一直阻塞直到数据可用,但在javadoc中没有提到会一直阻塞直到所有数据可用。看看javaapi中这种逻辑的实现,这也不是他们所做的假设。我建议使用该实现btw,而不是自己实现将数据读入
byte[]
数组:这并不是说将数据存储在内存中的
byte[]
数组中实际上是个好主意。我只是想添加这个注释来发布这种逻辑的一些替代方案,如果您将来需要它用于其他目的的话。谢谢大家的评论,所以我必须自己用java编写单元格,对吗?图像字段的数组是什么格式的?例如,它只是原始像素数据还是PNG或JPG格式?。。。您的注意事项非常重要:一般规则是永远不要在updateItem中执行任何可能昂贵的加载/计算,这样做将直接违背其设计意图(即极端的重用)。相反,在模型中只做一次(可能是实际数据的包装器或合成列)@kleopatra你是对的,我错了。我编辑了我的答案,删除了你提到的ImageView创建。这很好-谢谢你再强调一下注释:)
@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);
        }
    });
    ...
}
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;
}