1

i am trying to display a database table with blobs on a Jtable and i want the images to show but instead i get a set of codes in the column for images...Here are my codes:

this class retrieves my db table from database through a result set...

public class rs2Table {

public static TableModel resultSetToTableModel(ResultSet rs) {
    try {
        ResultSetMetaData metaData = rs.getMetaData();
        int numberOfColumns = metaData.getColumnCount();
        Vector<String> columnNames = new Vector<String>();

        // Get the column names
        for (int column = 0; column < numberOfColumns; column++) {
            columnNames.addElement(metaData.getColumnLabel(column + 1));
        }

        // Get all rows.
        Vector<Vector<Object>> rows = new Vector<Vector<Object>>();

        while (rs.next()) {
            Vector<Object> newRow = new Vector<Object>();

            for (int i = 1; i <= numberOfColumns; i++) {
                newRow.addElement(rs.getObject(i));
            }

            rows.addElement(newRow);
        }

        return new DefaultTableModel(rows, columnNames) {
            @Override
            public boolean isCellEditable(int row, int column) {
                //return all cells false
                return false;
            }
        };
    } catch (SQLException e) {
        JOptionPane.showMessageDialog(null,e);
        return null;
    }
}

this is where i try to display the database table with images and other fields...

private void retrvStaffList() {
    try {
        //this sql uses LEFT JOIN to merge tables with corresponding foreign keys
        //hence we it is going to display all staff with their specified info retrieved      from all the tables in ONE table...
        String sql = "SELECT DISTINCT s.StaffName, d.DeptName, b.age, b.telephone, b.email, b.address, t.position, t.salary, b.image FROM Staffs AS s\n"
                + "LEFT JOIN  Departments as d ON d.DepartmentID = s.DepartmentID\n"
                + "LEFT JOIN BioData AS b ON b.BioID = s.StaffID\n"
                + "LEFT JOIN StatusTable AS t ON t.ownerID = s.StaffID\n"
                + "ORDER BY s.StaffName";
        PreparedStatement pStmt2 = connect.prepareStatement(sql);
        rs = pStmt2.executeQuery();

                //get the staff table...
                staffTable.setModel(rs2Table.resultSetToTableModel(rs));

    } catch (SQLException ex) {
        Logger.getLogger(StaffList.class.getName()).log(Level.SEVERE, null, ex);
    }
}

i have retrieved the images for other purposes successfully but i dont know how i will go about inserting it in a JTable alongside other fields. i know i might have to use a byte to get the images and then pass it to an image icon like i did other times i retrieved the images for other purposes, but i dont know which of the methods to apply that.

please guys any hint is highly appreciated...thanks in advance

mKorbel
  • 109,525
  • 20
  • 134
  • 319
spynoble
  • 33
  • 1
  • 9
  • Shouldn't you be reading the contents of the blob column? Maybe through `ImageIO`? – MadProgrammer Aug 22 '14 at 01:44
  • @peeskillet that didnt work for me...i am using a vector for my rows while he used an Object array...i was able to do the override but didnt know how to add the icon to my newRow vector... – spynoble Aug 22 '14 at 03:05

1 Answers1

3

The goal is the get the image from the db into an ImageIcon so that you can take advantage of the default renderer, without having to provide your own renderer implementation (See How to use Tables: Editors and Renderers).

Since you haven't provided how you "have retrieved the images for other purposes successfully", I'll provide my own:

while (rs.next()) {
    Vector<Object> newRow = new Vector<Object>();

    for (int i = 1; i <= numberOfColumns; i++) {
        if (i == <imageColumn>) {  // ... whatever column is your image column
            Blob blob = rs.getBlob("image");
            int blobLength = (int) blob.length();  

            byte[] bytes = blob.getBytes(1, blobLength);
            blob.free();
            BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
            ImageIcon icon = new ImageIcon(img);  
            newRow.addElement(icon);  
        } else {
            newRow.addElement(rs.getObject(i));
        }
    }
    rows.addElement(newRow);
}

Then it's just a matter of overriding getColumnClass() on your DefaultTableModel (so the default renderer can render it as an ImageIcon), as explained in this answer.

You probably want to resize the row/column accordingly too, to fit the image. You can do that simply by doing something like

table.setRowHeight(height);
TableColumn column = table.getColumn("ColumnIdentifier");
column.setWidth(width);

Javadoc Resources:


EDIT

With SQLlite it seems you should read as rs.getBytes("image");. Also after further reading the docs, you could also simple construct the ImageIcon with the byte[] returned. new ImageIcon(rs.getBytes("image"));

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • thanks for your quick reply and your time. but i am getting a `java.sql.SQLException: not implemented by SQLite JDBC driver` against `blob blob = rs.getBlob("image")` any hints? thanks again bro... – spynoble Aug 22 '14 at 03:44
  • How exactly do you save the image? I'm not familiar with SQLlite. Are you saving it as a blob? Also you said you have been able to retrieve the images before. Why don't you explain how you did _that_. – Paul Samsotha Aug 22 '14 at 04:11
  • Maybe [this post](http://stackoverflow.com/q/7331310/2587435) will help with sqllite – Paul Samsotha Aug 22 '14 at 04:21
  • Or maybe [this link](http://kaninotes.blogspot.com/2011/12/inserting-and-retrieving-images-to.html). It actually uses `rs.getBytes("image")`. Maybe that's what you want. And just `ImageIO.read` from _that_ – Paul Samsotha Aug 22 '14 at 04:22
  • @peeskillet...the images were saved as a blob quite alright. but i think the sqlite driver i am using does not support the `getBlob(...)` method. normally i use get bytes like this `byte[] retrvdStaffImage = rs.getBytes("image"); ImageIcon icon = new ImageIcon(retrvdStaffImage);` and it works. i tried it with your code above but this time around i am seeing javax.swing.ImageIcon@...... under the image column...my guess is that the problem is with my override for the `getColumnClass()`... – spynoble Aug 22 '14 at 04:27
  • 1
    You need to make sure that that you return `ImageIcon.class` for the correct column. Remember the indices are 0 based, meaning they start at 0. Check that you aren't one off. – Paul Samsotha Aug 22 '14 at 04:29
  • @peeskillet...here is what i wrote under my override for `getColumnClass()`....` @Override`public Class> getColumnClass(int column) { switch (case 9: return ImageIcon.class; default: return Object.class;}` Please did i do anything wrong? thanks for your time bro... – spynoble Aug 22 '14 at 04:29
  • 1
    Looking at your query, image is the 9th, meaning in the table, the index should be 8 ;-) – Paul Samsotha Aug 22 '14 at 04:30
  • 1
    @peeskillet...it worked!!!!!!!!!! :) i changed the index to 8! ... thanks bro!!! Jeez! you have really relieved me of stress! thanks again...i owe you one :) – spynoble Aug 22 '14 at 04:33
  • @PaulSamsotha: Hi , i too have tried the above..and it has worked perfectly.But when i double click on the imageIcon in my jTable..the imageIcon gets changed to some string representation as javax.swing.ImageIcon@6fa56163..Here is my related post: https://stackoverflow.com/questions/61107627/double-clicking-on-an-imageicon-in-jtable-makes-the-imageicon-dissapear Could you please take a look ,thanks – pranay Apr 09 '20 at 14:16