dens14345
dens14345

Reputation: 302

How to get an image to the database, and set it as a "tooltipText()" for the table for a specific row

I am creating a program that has a JTable on it, populated by my database' data. each row , has a corresponding picture on it, so what i want to happen is that when i set my mouse cursor over that row , it will popUp a tooltipText which contain its picture ,

 tblListOfInmates = new JTable(){                       
                private static final long serialVersionUID = 8240878564742150750L;
                public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                        Component c = super.prepareRenderer(renderer, row, column);                     
                        if (c instanceof JComponent)  {
                            try{
                                    JComponent jc = (JComponent) c;    

                                    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");                                                                          
                                    con = DriverManager.getConnection("jdbc:odbc:RIM");
                                    st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);

                                    String x = tblListOfInmates.getModel().getValueAt(row, 6).toString();
                                    String sql = "select * from records where ID ='"+x+"'";
                                    rs = st.executeQuery(sql);
                                    java.net.URL url = new File(rs.getString("ID")).toURI().toURL();





                                     final String html = "<html><body>" + "<img src='"+ url + "' width=160 height=120> ";

                                    jc.setToolTipText(html + "<br/>"
                                            + getValueAt(row, column).toString()
                                            + ":  row, col (" + row + ", " + column + ")");                                     
                            }catch(Exception e){e.printStackTrace();}
                        }
                        return c;
                    }
            };

I got this error.

 at RecordManagementSystem.MainFrame$18.prepareRenderer(MainFrame.java:860)
at javax.swing.plaf.basic.BasicTableUI.paintCell(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)
at javax.swing.plaf.ComponentUI.update(Unknown Source)
at javax.swing.JComponent.paintComponent(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JViewport.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at javax.swing.JLayeredPane.paint(Unknown Source)
at javax.swing.JComponent.paintChildren(Unknown Source)
at javax.swing.JComponent.paintToOffscreen(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
at javax.swing.RepaintManager.paint(Unknown Source)
at javax.swing.JComponent.paint(Unknown Source)
at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
at java.awt.Container.paint(Unknown Source)
at java.awt.Window.paint(Unknown Source)
at javax.swing.RepaintManager$3.run(Unknown Source)
at javax.swing.RepaintManager$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
at javax.swing.RepaintManager.access$1100(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

I dont know how to properly do this, and i dont know if my Idea was right/good. Please tell me if you have a better Idea than this =)

Upvotes: 0

Views: 887

Answers (2)

Paul Samsotha
Paul Samsotha

Reputation: 208994

I'm guessing the images you have are trying to load in the tool tip are blobs in the db. The problem with this is that a url can't be made from a database object. You can have the url stored in the db to a url in the file system, but I think that may be out of the question because you don't want to have images both in the database and the file system.

Maybe what you should do is when you're loading the TableModel, all the corresponding images, save to the file system (temporarily). You can do that with File.createTempFile. You can get a URL from that img.

Also note you'll want to do this in background thread. See Concurrency with Swing

You can then access those images from the file system, which will be alot more efficient than trying to access from the db one at a time. You can then use the url from the file system in the html String using File.getUri().getUrl()

You can have a method that clears the file system of those images. You might want to call it every time a new set of table data is loaded, and/or when the program closes.

You can load an image from a db blob and write it to file like this

Blob blob = rs.getBlob("img");
int blobLength = (int) blob.length();  

byte[] bytes = blob.getBytes(1, blobLength);
blob.free();
BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
ImageIO.write(img, "png", new File("..."));

Here's an example with most of the above mentioned points. Except the background thread. Two lazy for that, but you'll want to do that every time your update your table model from the db

enter image description here

import java.awt.Component;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.net.URL;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

public class TableToolTip {

    private Map<String, URL> fileMap;

    public TableToolTip() {
        fileMap = new HashMap<>();
        JTable table = createTable();

        JFrame frame = new JFrame();
        frame.add(new JScrollPane(table));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private JTable createTable() {
        JTable table = new JTable(createModel()) {

            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                if (c instanceof JComponent) {
                    JComponent jc = (JComponent) c;
                    URL url = fileMap.get((String) getValueAt(row, column));
                    String html = "<html><body>"
                            + "<img src='"
                            + url
                            + "' width=150 height=150> ";

                    jc.setToolTipText(html + "<br/>"
                            + getValueAt(row, column).toString()
                            + ":  row, col (" + row + ", " + column + ")"
                            + "</body></html>");
                }
                return c;
            }
        };
        return table;
    }

    private DefaultTableModel createModel() {
        DefaultTableModel model = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost/mario", "root", "password");
            PreparedStatement ps = conn.prepareStatement("select * from characters");
            ResultSet rs = ps.executeQuery();
            ResultSetMetaData rsMeta = rs.getMetaData();
            String colTitle = rsMeta.getColumnName(1);

            model = new DefaultTableModel(new String[]{colTitle}, 0);

            while (rs.next()) {
                String name = rs.getString("NAME");
                model.addRow(new Object[]{name});
                File temp = File.createTempFile(name, ".png");
                Blob blob = rs.getBlob("IMG");
                int blobLength = (int) blob.length();
                byte[] bytes = blob.getBytes(1, blobLength);
                blob.free();
                BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
                ImageIO.write(img, "png", temp);

                URL fileURL = temp.toURI().toURL();
                fileMap.put(name, fileURL);
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return model;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TableToolTip();
            }
        });
    }
}

Upvotes: 3

mKorbel
mKorbel

Reputation: 109813

  • every Key and Mouse Events are immediatelly fired inside TableCellRenderer, then exception from RepaintManager is generated from long and heavy JDBC task, don't do that, nor to opening JDBC Connection, there is generated bunch of Key and Mouse Events, especially Mouse Events are per each of pixels

  • load all images to local variables as Icon/ImageIcon, event. to the array of Icon/ImageIcon,

Upvotes: 4

Related Questions