2

So I'm trying to display images stored in my database as Blob to an image column in table view. All of the other data is displayed well except for those in the image column. I've been struggling for days but still unable to find a solution.

Here's what I have tried so far:

public void loadPropertyData() throws IOException {
    try {
        Connection connection = OracleConnect.getConnection();
        String query = "SELECT id, property, image, price, contact, location, status FROM property" + getProfileName().getText();
        PreparedStatement statement = connection.prepareStatement(query);
        ResultSet resultSet = statement.executeQuery();
        ObservableList<Property> propertyList = FXCollections.observableArrayList();

        while (resultSet.next()) {
            int id = resultSet.getInt("id");
            String property = resultSet.getString("property");
            Blob imageBlob = resultSet.getBlob("image");
            Image image = null;
            if (imageBlob != null) {
                InputStream is = imageBlob.getBinaryStream();
                image = new Image(is);
            }
            String price = resultSet.getString("price");
            String contact = resultSet.getString("contact");
            String location = resultSet.getString("location");
            String status = resultSet.getString("status");

            Property propertyObj = new Property(id, property, image, price, contact, location, status);
            propertyList.add(propertyObj);
        }

        propertyIDColumn.setCellValueFactory(cellData -> cellData.getValue().idProperty().asObject());
        propertyColumn.setCellValueFactory(cellData -> cellData.getValue().propertyProperty());
        propertyImageColumn.setCellValueFactory(col -> col.getValue().imageProperty());
        propertyImageColumn.setCellFactory(col -> {
            TableCell<Property, Image> cell = new TableCell<Property, Image>() {
                private final ImageView imageView = new ImageView();

                {
                    setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                }

                @Override
                protected void updateItem(Image item, boolean empty) {
                    super.updateItem(item, empty);

                    if (empty || item == null) {
                        imageView.setImage(null);
                        setGraphic(null);
                    } else {
                        imageView.setImage(item);
                        setGraphic(imageView);
                    }
                }
            };

            return cell;
        });
        propertyPriceColumn.setCellValueFactory(cellData -> cellData.getValue().priceProperty());
        propertyContactColumn.setCellValueFactory(cellData -> cellData.getValue().contactProperty());
        propertyLocationColumn.setCellValueFactory(cellData -> cellData.getValue().locationProperty());
        propertyStatusColumn.setCellValueFactory(cellData -> cellData.getValue().statusProperty());

        propertyTableView.setItems(propertyList);

        resultSet.close();
        statement.close();
        connection.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

Edit: Here is my Property model

Property {
    private IntegerProperty id;
    private StringProperty property;
    private ObjectProperty<Image> image;
    private StringProperty price;
    private StringProperty contact;
    private StringProperty location;
    private StringProperty status;

    public Property(int id, String property, Image image, String price, String contact, String location, String status) {
        this.id = new SimpleIntegerProperty(id);
        this.property = new SimpleStringProperty(property);
        this.image = new SimpleObjectProperty<>(image);
        this.price = new SimpleStringProperty(price);
        this.contact = new SimpleStringProperty(contact);
        this.location = new SimpleStringProperty(location);
        this.status = new SimpleStringProperty(status);
    }

    public IntegerProperty idProperty() {
        return id;
    }

    public int getId() {
        return id.get();
    }

    public void setId(int id) {
        this.id.set(id);
    }

    public StringProperty propertyProperty() {
        return property;
    }

    public String getProperty() {
        return property.get();
    }

    public void setProperty(String property) {
        this.property.set(property);
    }

    public ObjectProperty<Image> imageProperty() {
        return image;
    }

    public Image getImage() {
        return image.get();
    }

    public void setImage(Image image) {
        this.image.set(image);
    }

    public StringProperty priceProperty() {
        return price;
    }

    public String getPrice() {
        return price.get();
    }

    public void setPrice(String price) {
        this.price.set(price);
    }

    public StringProperty contactProperty() {
        return contact;
    }

    public String getContact() {
        return contact.get();
    }

    public void setContact(String contact) {
        this.contact.set(contact);
    }

    public StringProperty locationProperty() {
        return location;
    }

    public String getLocation() {
        return location.get();
    }

    public void setLocation(String location) {
        this.location.set(location);
    }

    public StringProperty statusProperty() {
        return status;
    }

    public String getStatus() {
        return status.get();
    }

    public void setStatus(String status) {
        this.status.set(status);
    }
}

Here is what I used to create table in my database

@FXML
private void Signup() {
    Connection connection = null;
    PreparedStatement createTableStatement = null;
    PreparedStatement createSequenceStatement = null;
    PreparedStatement insertStatement = null;

    try {
        connection = OracleConnect.getConnection();

        // Create table
        String createTableProperty = "CREATE TABLE property" + signupTF.getText() +
                " (" +
                "    id NUMBER," +
                "    property VARCHAR2(50)," +
                "    image BLOB," +
                "    price VARCHAR2(50)," +
                "    contact VARCHAR2(50)," +
                "    location VARCHAR2(50)," +
                "    status VARCHAR2(50)" +
                ")";
        createTableStatement = connection.prepareStatement(createTableProperty);
        createTableStatement.execute();

        // Create sequence
        String createSequenceProperty = "CREATE SEQUENCE property" +
                signupTF.getText() + "_seq " +
                "START WITH 1 " +
                "INCREMENT BY 1 " +
                "MINVALUE 1 " +
                "NOCACHE";
        createSequenceStatement = connection.prepareStatement(createSequenceProperty);
        createSequenceStatement.execute();

        // Insert data
        String insertData = "INSERT INTO property" + signupTF.getText() +
                " (id, property, image, price, contact, location, status)" +
                " VALUES (property" + signupTF.getText() + "_seq.nextval, ?, ?, ?, ?, ?, ?)";
        insertStatement = connection.prepareStatement(insertData);
        insertStatement.setString(1, "Property Name"); // Set the property name
        insertStatement.setBlob(2, new FileInputStream(new File("path/to/image.jpg"))); // Set the image file
        insertStatement.setString(3, "Price"); // Set the price
        insertStatement.setString(4, "Contact"); // Set the contact
        insertStatement.setString(5, "Location"); // Set the location
        insertStatement.setString(6, "Status"); // Set the status
        insertStatement.execute();

    } catch (SQLException e) {
        if (e.getErrorCode() == 1400) {
            JOptionPane.showMessageDialog(null, "Please enter required information");
        } else {
            JOptionPane.showMessageDialog(null, "An error occurred: " + e.getMessage());
        }
    } catch (FileNotFoundException e) {
        JOptionPane.showMessageDialog(null, "Image file not found: " + e.getMessage());
    } finally {
        try {
            if (insertStatement != null) {
                insertStatement.close();
            }
            if (createSequenceStatement != null) {
                createSequenceStatement.close();
            }
            if (createTableStatement != null) {
                createTableStatement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, "An error occurred while closing the resources: " + e.getMessage());
        }
    }
}

Here is the data from my table in the database

data

Here is what's displayed in the table view

table view

6
  • 3
    I can't find propertyImageColumn.setCellValueFactory. I think you must set a cell value factory for each column in the TableView. Note that I don't have access to your database so I can't verify whether your code that retrieves data from the database is correct. Commented Jan 14, 2024 at 13:29
  • 1
    stackoverflow.com/questions/77512467/… Commented Jan 14, 2024 at 19:28
  • 1
    stackoverflow.com/questions/75656158/… Commented Jan 14, 2024 at 19:29
  • 1
    stackoverflow.com/questions/77536529/… Commented Jan 14, 2024 at 19:32
  • 1
    You could also use an image cache for better performance. Commented Jan 14, 2024 at 21:08

2 Answers 2

2

It starts with the class that serves as the data model for the TableView. In the below code, that class is ImagItem. The class must contain an attribute for each column of the TableView – which must be an ObservableValue. In the below code, there is only one column. Hence class ImagItem contains a single attribute. For each attribute you need three methods.

  • One that returns the value wrapped by the ObservableValue.
  • One that assigns the wrapped value.
  • One that returns the ObservableValue.

Now you just need to define the cell value factory and the cell factory for the columns of the TableView. The cell value factory is basically a method that receives a CellDataFeatures and returns an ObservableValue. In the below code, in the lambda expression that serves as that method, c is an instance of CellDataFeatures<ImagItem, Image> and its getValue method returns an instance of ImagItem, so you want that method to return the attribute of ImagItem – hence the call to imageProperty. Note that the names of the methods in class ImagItem are according to the accepted convention.

Finally, the cell factory is a method that receives a TableColumn and needs to return a TableCell. In the below code I have written an anonymous inner class which implicitly extends class TableCell and I have overridden method updateItem. TableCell extends Labeled and hence has a text property and a graphic property. You want your TableCell to display an image only, hence, in the below code, I simply wrap the method parameter (img) in an ImageView and set that as the graphic for the TableCell.

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;

public class Test extends Application {
    private static final Path  ROOT = Paths.get("C:\\Users\\USER\\Pictures");

    @Override
    public void start(Stage primaryStage) throws Exception {
        Group root = new Group();
        TableView<ImagItem> table = new TableView<ImagItem>();
        TableColumn<ImagItem, Image> imgCol = new TableColumn<ImagItem, Image>("Image");
        imgCol.setCellValueFactory(c -> c.getValue().imageProperty());
        imgCol.setCellFactory(c -> {
            return new TableCell<ImagItem, Image>() {
                protected void updateItem(Image img, boolean empty) {
                    super.updateItem(img, empty);
                    setText(null);
                    if (img != null  &&  !empty) {
                        ImageView imgVw = new ImageView(img);
                        setGraphic(imgVw);
                    }
                    else {
                        setGraphic(null);
                    }
                }
            };
        });
        table.getColumns().add(imgCol);
        ObservableList<ImagItem> items = FXCollections.observableArrayList(getImages());
        table.setItems(items);
        root.getChildren().add(table);
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private ImagItem getImage(String name) throws MalformedURLException {
        Path path = ROOT.resolve(name);
        URI uri = path.toUri();
        URL url = uri.toURL();
        Image img = new Image(url.toExternalForm());
        ImagItem ii = new ImagItem(img);
        return ii;
    }

    private List<ImagItem> getImages() throws MalformedURLException {
        List<ImagItem> list = new ArrayList<>();
        list.add(getImage("284kd.png"));
        list.add(getImage("dynamite.png"));
        return list;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

class ImagItem {
    private SimpleObjectProperty<Image>  image;

    public ImagItem(Image img) {
        image = new SimpleObjectProperty<Image>(this, "image", img);
    }

    public Image getImage() {
        return image.get();
    }

    public void setImage(Image img) {
        image.set(img);
    }

    public SimpleObjectProperty<Image> imageProperty() {
        return image;
    }
}

Here is a screen capture:

screen capture

Edit

(19 January 2024)
The images were not displayed for you because you probably did not insert them correctly into the database. The below code demonstrates how to update the images in the database (because I assume that you have already inserted them – albeit incorrectly).

For inserting, refer to the accepted answer in this SO question:
How to write / update Oracle blob in a reliable way?

I adapted that answer to update the database (because I also initially incorrectly inserted the images into the database).

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class UpdImOra {

    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("ARGS: file, id");
            System.exit(1);
        }
        File f = new File(args[0]);
        long len = f.length();
        int id = Integer.parseInt(args[1]);
        String sql = """
update PROPERTIES
   set IMAGE = ?
 where ID = ?
                """;
        try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@//host:1521/sid",
                                                           "George",
                                                           "Best");
             FileInputStream fis = new FileInputStream(f);
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setBinaryStream(1, fis, len);
            ps.setInt(2, id);
            int count = ps.executeUpdate();
            String plural = count == 1 ? "" : "s";
            System.out.printf("Updated %d row%s.%n", count, plural);
        }
        catch (IOException | SQLException x) {
            x.printStackTrace();
        }

    }
}

Now the images are displayed in the TableView.

import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class OraFxApp extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        TableView<Property> table = new TableView<>();
        TableColumn<Property, Number> idCol = new TableColumn<>("ID");
        idCol.setCellValueFactory(c -> c.getValue().idProperty());
        TableColumn<Property, String> propertyCol = new TableColumn<>("PROPERTY");
        propertyCol.setCellValueFactory(c -> c.getValue().propertyProperty());
        TableColumn<Property, Image> imageCol = new TableColumn<>("IMAGE");
        imageCol.setCellValueFactory(c -> c.getValue().imageProperty());
        imageCol.setCellFactory(c -> {
            return new TableCell<Property, Image>() {
                protected void updateItem(Image img, boolean empty) {
                    super.updateItem(img, empty);
                    setText(null);
                    if (img != null  &&  !empty) {
                        ImageView imgVw = new ImageView(img);
                        setGraphic(imgVw);
                    }
                    else {
                        setGraphic(null);
                    }
                }
            };
        });
        TableColumn<Property, Number> priceCol = new TableColumn<>("PRICE");
        priceCol.setCellValueFactory(c -> c.getValue().priceProperty());
        TableColumn<Property, String> contactCol = new TableColumn<>("CONTACT");
        contactCol.setCellValueFactory(c -> c.getValue().contactProperty());
        TableColumn<Property, String> locationCol = new TableColumn<>("LOCATION");
        locationCol.setCellValueFactory(c -> c.getValue().locationProperty());
        TableColumn<Property, String> statusCol = new TableColumn<>("STATUS");
        statusCol.setCellValueFactory(c -> c.getValue().statusProperty());
        ObservableList<TableColumn<Property, ?>> columns = table.getColumns();
        columns.add(idCol);
        columns.add(propertyCol);
        columns.add(imageCol);
        columns.add(priceCol);
        columns.add(contactCol);
        columns.add(locationCol);
        columns.add(statusCol);
        List<Property> list = loadPropertyData();
        ObservableList<Property> items = FXCollections.observableArrayList(list);
        table.setItems(items);
        BorderPane root = new BorderPane();
        root.setCenter(table);
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private List<Property> loadPropertyData() throws SQLException {
        String sql = """
select ID
      ,PROPERTY
      ,IMAGE
      ,PRICE
      ,CONTACT
      ,LOCATION
      ,STATUS
  from PROPERTIES
                """;
        List<Property> list = new ArrayList<>();
        try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@//host:1521/sid",
                                                           "George",
                                                           "Best");
             Statement s = conn.createStatement();
             ResultSet rs = s.executeQuery(sql)) {
            while (rs.next()) {
                int iden = rs.getInt(1);
                String prop = rs.getString(2);
                Blob blob = rs.getBlob(3);
                InputStream is = blob.getBinaryStream();
                Image img = new Image(is);
                int cost = rs.getInt(4);
                String liaison = rs.getString(5);
                String place = rs.getString(6);
                String situation = rs.getString(7);
                Property p = new Property(iden, prop, img, cost, liaison, place, situation);
                list.add(p);
            }
        }
        return list;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

class Property {
    private SimpleObjectProperty<Number>  id;
    private SimpleStringProperty  property;
    private SimpleObjectProperty<Image>  image;
    private SimpleObjectProperty<Number>  price;
    private SimpleStringProperty  contact;
    private SimpleStringProperty  location;
    private SimpleStringProperty  status;

    public Property(int iden,
                    String prop,
                    Image  img,
                    int    cost,
                    String liaison,
                    String place,
                    String situation) {
        id = new SimpleObjectProperty<>(this, "id", Integer.valueOf(iden));
        property = new SimpleStringProperty(this, "property", prop);
        image = new SimpleObjectProperty<>(this, "image", img);
        price = new SimpleObjectProperty<>(this, "price", Integer.valueOf(cost));
        contact = new SimpleStringProperty(this, "contact", liaison);
        location = new SimpleStringProperty(this, "location", place);
        status = new SimpleStringProperty(this, "status", situation);
    }

    public Number getId() {
        return id.get();
    }

    public void setId(Number iden) {
        id.set(iden);
    }

    public SimpleObjectProperty<Number> idProperty() {
        return id;
    }

    public String getProperty() {
        return property.get();
    }

    public void setProperty(String prop) {
        property.set(prop);
    }

    public SimpleStringProperty propertyProperty() {
        return property;
    }

    public Image getImage() {
        return image.get();
    }

    public void setImage(Image img) {
        image.set(img);
    }

    public SimpleObjectProperty<Image> imageProperty() {
        return image;
    }

    public Number getPrice() {
        return price.get();
    }

    public void setPrice(Number iden) {
        price.set(iden);
    }

    public SimpleObjectProperty<Number> priceProperty() {
        return price;
    }

    public String getContact() {
        return contact.get();
    }

    public void setContact(String prop) {
        contact.set(prop);
    }

    public SimpleStringProperty contactProperty() {
        return contact;
    }

    public String getLocation() {
        return location.get();
    }

    public void setLocation(String prop) {
        location.set(prop);
    }

    public SimpleStringProperty locationProperty() {
        return location;
    }

    public String getStatus() {
        return status.get();
    }

    public void setStatus(String prop) {
        status.set(prop);
    }

    public SimpleStringProperty statusProperty() {
        return status;
    }
}

Screen capture:

screen capture 2

Sign up to request clarification or add additional context in comments.

6 Comments

This seems to retrieve images from available URLs but I'd rather want to populate the image data saved as Blob datatype from the table in database. Is there a way to do that? I just modified the post to contain screenshots of my table in database and table view.
@phamnguyen I suggest that you first modify your Property class and make its attributes ObservableValues - as I explained in my answer. Then add methods for each attribute - as I also explained in my answer. Then change your cell factory and cell value factory definitions - again, as explained in my answer. Then, if you are still having the same problem, we can look at how you retrieve the images from the database.
I just modified my Property model, wrapped its attributes in ObservableValue, added three methods for each attribute and redefined cell value factory and cell factory. The problem still seems to remain as all of the other data is displayed in the table view but image column. I included the edited code in the post so you can see if I'm heading in the right direction.
@phamnguyen Your addition of JavaFX properties to your Property class is fine as far as that goes. I know Property is part of your name (as in representing physical property). However, as long as you have control over naming, I don't suggest naming your own class Property in a JavaFX application, because it can easily get confused with JavaFX properties. Just choose some other name.
@phamnguyen As you continue to experience problems, provide a minimal reproducible example. That will allow somebody to reproduce your issue by just copying and pasting your code and running it with no change or addition. You can't expect to get debug assistance for code that nobody else can run. As an answerer will not have your database, stub out all of the database code, and use hardcoded data instead.
|
1

Populates a database with data, sourcing some test images from URLs, then retrieves the data from the database and displays it in a JavaFX Table.

sour mikan

module-info.java

module org.example.h2image {
    requires javafx.controls;
    requires java.sql;

    exports org.example.h2image;
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>h2image</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>h2image</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>21.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>2.2.224</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>21</source>
                    <target>21</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

ImageTableApplication.java

package org.example.h2image;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.image.Image;
import javafx.stage.Stage;

import java.util.List;

public class ImageTableApplication extends Application {
    private final PropertyDao propertyDao = new PropertyDao();

    @Override
    public void init() {
        propertyDao.createDB();
        propertyDao.populateDB();
    }

    @Override
    public void start(Stage stage) {
        TableView<PropertyInfo> tableView = new TableView<>(
                propertyDao.findProperties()
        );
        tableView.setPrefSize(600, 350);
        tableView.setStyle("-fx-font-size: 20px");

        TableColumn<PropertyInfo, Integer> idColumn = new TableColumn<>("ID");
        idColumn.setCellValueFactory(cellData -> cellData.getValue().idProperty().asObject());

        TableColumn<PropertyInfo, String> nameColumn = new TableColumn<>("Property");
        nameColumn.setPrefWidth(100);
        nameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());

        TableColumn<PropertyInfo, Image> imageColumn = new TableColumn<>("Image");
        imageColumn.setCellValueFactory(cellData -> cellData.getValue().imageProperty());
        imageColumn.setCellFactory(col -> new ImageCell<>());

        TableColumn<PropertyInfo, String> priceColumn = new TableColumn<>("Price");
        priceColumn.setCellValueFactory(cellData -> cellData.getValue().priceProperty());

        TableColumn<PropertyInfo, String> locationColumn = new TableColumn<>("Location");
        locationColumn.setPrefWidth(100);
        locationColumn.setCellValueFactory(cellData -> cellData.getValue().locationProperty());

        TableColumn<PropertyInfo, String> statusColumn = new TableColumn<>("Status");
        statusColumn.setCellValueFactory(cellData -> cellData.getValue().statusProperty());

        tableView.getColumns().setAll(
                List.of(
                        idColumn,
                        nameColumn,
                        imageColumn,
                        priceColumn,
                        locationColumn,
                        statusColumn
                )
        );

        stage.setScene(new Scene(tableView));
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

ImageCell.java

package org.example.h2image;

import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

class ImageCell<S> extends TableCell<S, Image> {
    private final ImageView imageView = new ImageView();

    public ImageCell() {
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    }

    @Override
    protected void updateItem(Image item, boolean empty) {
        super.updateItem(item, empty);

        if (empty || item == null) {
            imageView.setImage(null);
            setGraphic(null);
        } else {
            imageView.setImage(item);
            setGraphic(imageView);
        }
    }
}

PropertyInfo.java

package org.example.h2image;

import javafx.beans.property.*;
import javafx.scene.image.Image;

public class PropertyInfo {
    private final IntegerProperty id;
    private final StringProperty name;
    private final ObjectProperty<Image> image;
    private final StringProperty price;
    private final StringProperty contact;
    private final StringProperty location;
    private final StringProperty status;

    public PropertyInfo(int id, String name, Image image, String price, String contact, String location, String status) {
        this.id = new SimpleIntegerProperty(id);
        this.name = new SimpleStringProperty(name);
        this.image = new SimpleObjectProperty<>(image);
        this.price = new SimpleStringProperty(price);
        this.contact = new SimpleStringProperty(contact);
        this.location = new SimpleStringProperty(location);
        this.status = new SimpleStringProperty(status);
    }

    public IntegerProperty idProperty() {
        return id;
    }

    public int getId() {
        return id.get();
    }

    public void setId(int id) {
        this.id.set(id);
    }

    public StringProperty nameProperty() {
        return name;
    }

    public String getName() {
        return name.get();
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public ObjectProperty<Image> imageProperty() {
        return image;
    }

    public Image getImage() {
        return image.get();
    }

    public void setImage(Image image) {
        this.image.set(image);
    }

    public StringProperty priceProperty() {
        return price;
    }

    public String getPrice() {
        return price.get();
    }

    public void setPrice(String price) {
        this.price.set(price);
    }

    public StringProperty contactProperty() {
        return contact;
    }

    public String getContact() {
        return contact.get();
    }

    public void setContact(String contact) {
        this.contact.set(contact);
    }

    public StringProperty locationProperty() {
        return location;
    }

    public String getLocation() {
        return location.get();
    }

    public void setLocation(String location) {
        this.location.set(location);
    }

    public StringProperty statusProperty() {
        return status;
    }

    public String getStatus() {
        return status.get();
    }

    public void setStatus(String status) {
        this.status.set(status);
    }
}

PropertyDao.java

package org.example.h2image;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.image.Image;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.*;

public class PropertyDao {
    private static final String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";
    private static final String CREATE_PROPERTY_TABLE_DDL = // language=SQL
            """
            CREATE TABLE property
            ( 
                id NUMBER, 
                property VARCHAR2(50), 
                image BLOB, 
                price VARCHAR2(50), 
                contact VARCHAR2(50), 
                location VARCHAR2(50), 
                status VARCHAR2(50) 
            );
            """;
    private static final String CREATE_PROPERTY_SEQ_DDL = // language=SQL
            """
            CREATE SEQUENCE property_seq
            START WITH 1
            INCREMENT BY 1
            MINVALUE 1;
            """;
    private static final String INSERT_PROPERTY_SQL = // language=SQL
            """
            INSERT INTO property
              (id, property, image, price, contact, location, status)
            VALUES 
              ((select next value for property_seq), ?, ?, ?, ?, ?, ?);
            """;

    private static final String FIND_PROPERTY_SQL = // language=SQL
            """
            SELECT id, property, image, price, contact, location, status FROM property
            """;

    public void createDB() {
        try (
                Connection connection = DriverManager.getConnection(JDBC_URL);
                PreparedStatement createTableStatement = connection.prepareStatement(CREATE_PROPERTY_TABLE_DDL);
                PreparedStatement createSequenceStatement = connection.prepareStatement(CREATE_PROPERTY_SEQ_DDL);
        ) {
            createTableStatement.execute();
            createSequenceStatement.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void populateDB() {
        try (
                Connection connection = DriverManager.getConnection(JDBC_URL);
                PreparedStatement insertStatement = connection.prepareStatement(INSERT_PROPERTY_SQL)
        ) {
            int i = 0;
            for (PropertyInfo propertyInfo: TestData.TEST_PROPERTIES) {
                try (InputStream imageInputStream = new URI(TestData.TEST_IMAGE_LOCS.get(i)).toURL().openStream()) {
                    insertStatement.setString(1, propertyInfo.getName());
                    insertStatement.setBlob(2, imageInputStream);
                    insertStatement.setString(3, propertyInfo.getPrice());
                    insertStatement.setString(4, propertyInfo.getContact());
                    insertStatement.setString(5, propertyInfo.getLocation());
                    insertStatement.setString(6, propertyInfo.getStatus());
                    insertStatement.execute();

                    i++;
                } catch (URISyntaxException | IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public ObservableList<PropertyInfo> findProperties() {
        try (
                Connection connection = DriverManager.getConnection(JDBC_URL);
                PreparedStatement statement = connection.prepareStatement(FIND_PROPERTY_SQL);
                ResultSet resultSet = statement.executeQuery()
        ) {
            ObservableList<PropertyInfo> propertyList = FXCollections.observableArrayList();

            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String property = resultSet.getString("property");
                Blob imageBlob = resultSet.getBlob("image");
                Image image = null;
                if (imageBlob != null) {
                    InputStream is = imageBlob.getBinaryStream();
                    image = new Image(is);
                }
                String price = resultSet.getString("price");
                String contact = resultSet.getString("contact");
                String location = resultSet.getString("location");
                String status = resultSet.getString("status");

                PropertyInfo propertyObj = new PropertyInfo(id, property, image, price, contact, location, status);
                propertyList.add(propertyObj);
            }

            return propertyList;
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return FXCollections.observableArrayList();
    }
}

TestData.java

package org.example.h2image;

import java.util.List;

public class TestData {
    public static final List<PropertyInfo> TEST_PROPERTIES = List.of(
            new PropertyInfo(
                    1,
                    "Mikan",
                    null,
                    "$2.00",
                    "The demon girl next door",
                    "Tokyo",
                    "Very Sour"
            ),
            new PropertyInfo(
                    2,
                    "Lemon",
                    null,
                    "$1.00",
                    "Mami Tomoe",
                    "Osaka",
                    "Very Sweet"
            )
    );
    public static final List<String> TEST_IMAGE_LOCS = List.of(
            "https://www.iconarchive.com/download/i107438/google/noto-emoji-food-drink/32344-tangerine.128.png",
            "https://www.iconarchive.com/download/i107439/google/noto-emoji-food-drink/32345-lemon.128.png"
    );
}

Test Images

mikan lemon

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.