0

I'm trying to display images retrieve from MySQL database of blob datatype. Could not figure out what is the problem that causes the image column to display data like this [B@29b8e4f7 instead of image icon.

DefaultTableModel model = new DefaultTableModel(new Object[]{
    "image", "item_name", "quantity","price", "category", "color", "size"}, 0){
        @Override
        public Class<?> getColumnClass(int column) {
            switch(column){
                case 0: return ImageIcon.class;
                default: return String.class;
            }
        }
    };

    myTable.setModel(model);

...

         ResultSet rs = database.getRS();

            int columns = rs.getMetaData().getColumnCount();

            while(rs.next()){
                Object[] row = new Object[columns];
                for(int i = 1; i <= columns; i++){                        
                    row[i-1] = rs.getObject(i);

                }
                DefaultTableModel defmodel = (DefaultTableModel) tableItem.getModel();
                defmodel.insertRow(rs.getRow()-1, row);

            }
kaizen
  • 1,580
  • 4
  • 26
  • 50
  • The data in the model is (from what I can guess) is a `byte[]`, not a valid image. How is the data stored in the database (by what means)? – MadProgrammer May 01 '15 at 08:26
  • @MadProgrammer In localhost/phpmyadmin. The Type is MediumBlob. – kaizen May 01 '15 at 08:30
  • @MadProgrammer The value stored is [BLOB - 17.1 KiB]. – kaizen May 01 '15 at 08:31
  • Yeah, but are you storing the pixel data or the actual physical image (jpg/png)? – MadProgrammer May 01 '15 at 08:31
  • Try displaying the images in a `JLabel` (and get that working) before the more tricky task of displaying them in a table. – Andrew Thompson May 01 '15 at 08:32
  • @MadProgrammer I used preparedstatement.setBlob(1, InputStream); – kaizen May 01 '15 at 08:35
  • Okay, so I would suggest you either get the byte array and wrap in a `ByteArrayInputStream` and run that through `ImageIO.read` or get the `InputStream` from the blob via the `ResultSet` and run that through `ImageIO.read` – MadProgrammer May 01 '15 at 08:36
  • Something like [this](http://stackoverflow.com/questions/13833089/how-to-show-an-image-from-ms-access-to-jpanel-in-java-netbeans/13833233#13833233) for example – MadProgrammer May 01 '15 at 08:37
  • @AndrewThompson I tried it with JLabel and it's working. This is what i did. imageData = rs.getBytes("image"); mylabel.setIcon(new ImageIcon(imageData)); But i'm trying to figure out how to display it on table cells. – kaizen May 01 '15 at 08:47
  • 1
    @ChaoQunLi But, that's not what you're doing with the data in the `TableModel`, you're just passing it the `byte` array... – MadProgrammer May 01 '15 at 08:50

1 Answers1

1

Since you used preparedstatement.setBlob(1, InputStream); to store the image, I have to assume that you stored the physical image file/format and not just the pixel data.

You need to read back this image format and convert to a supported image format for Swing/Java.

Start by getting a Blob reference to the database field...

Blob blob = rs.getBlob(1);

Once you have a Blob, you can use it's binary InputStream and read the data...

BufferedImage image = null;
try (InputStream is = blob.getBinaryStream()) {
    image = ImageIO.read(is);
} catch (IOException exp) {
    exp.printStackTrace();
}

Now, you can make it an ImageIcon using new ImageIcon(image) and put this within your table model...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Sorry, I'm kind of confused about this part. try (InputStream is = rs.getBinaryStream()) – kaizen May 01 '15 at 09:33
  • [try-with-resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) – MadProgrammer May 01 '15 at 09:34
  • is this line optional? Blob blob = rs.getBlob(1); – kaizen May 01 '15 at 09:42
  • Yes and no, it's optional only if your use `rs.getBinaryStream(1)` instead, either way, you need to get the binary `InputStream` (and sorry, I see where the confusion is) – MadProgrammer May 01 '15 at 09:44
  • Assuming you know the size of the cell before hand, it's easy. Otherwise it becomes, well, messy. http://stackoverflow.com/questions/11959758/java-maintaining-aspect-ratio-of-jpanel-background-image/11959928#11959928 for scaling an image – MadProgrammer May 01 '15 at 09:51
  • May i know how can i scale the loaded image to fit the table cell width & height? – kaizen May 01 '15 at 09:51
  • You need to use a custom `TableCellRenderer`, start with [Using Custom Renderers](https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#renderer). You can get the the actual cell bonds using [`JTable#getCellRect`](http://docs.oracle.com/javase/7/docs/api/javax/swing/JTable.html#getCellRect(int,%20int,%20boolean)) – MadProgrammer May 01 '15 at 10:28
  • Another problem arises. Some of the table cells doesn't contain image which causes exceptions. How can i handle this problem? – kaizen May 02 '15 at 06:29
  • Then check to see of Blob is null or try [ResultSet#wasNull](http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#wasNull()) – MadProgrammer May 02 '15 at 06:46
  • That works. By the way, why is it loading the images with delay. I added a ListSelectionListener to the JTable. Everytime i clicked a row, it loads the image to a JLabel with delay before the row gets highlighted. – kaizen May 02 '15 at 10:37
  • It takes to time for the databse to extract the image data, transmit to your program, load the physical image and the render it. You do the loading of the image SwingWorker, which would allow the UI to continue responding while you load the image – MadProgrammer May 02 '15 at 11:25