17

Can someone point me in the right direction on how to add an image into Java Table cell.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
dwayne
  • 1,587
  • 3
  • 11
  • 5

4 Answers4

36

JTable already provides a default renderer for icons. You just need to tell the table what data is stored in a given column so it can choose the appropriate renderer. This is done by overriding the getColumnClass(...) method:

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableIcon extends JPanel
{
    public TableIcon()
    {
        Icon aboutIcon = new ImageIcon("about16.gif");
        Icon addIcon = new ImageIcon("add16.gif");
        Icon copyIcon = new ImageIcon("copy16.gif");

        String[] columnNames = {"Picture", "Description"};
        Object[][] data =
        {
            {aboutIcon, "About"},
            {addIcon, "Add"},
            {copyIcon, "Copy"},
        };

        DefaultTableModel model = new DefaultTableModel(data, columnNames)
        {
            //  Returning the Class of each column will allow different
            //  renderers to be used based on Class
            public Class getColumnClass(int column)
            {
                return getValueAt(0, column).getClass();
            }
        };
        JTable table = new JTable( model );
        table.setPreferredScrollableViewportSize(table.getPreferredSize());

        JScrollPane scrollPane = new JScrollPane( table );
        add( scrollPane );
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("Table Icon");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TableIcon());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

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

}
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Yeah it works! Thanks. Question: Why the setPreferredScrollableViewportSize line? Seems to work fine without it. – Stefan Reich Sep 21 '16 at 15:27
  • @StefanReich, It has nothing to do with displaying the icon in the table. The size of the frame is different when you do the pack(). Depends on your requirement if you use the method or not. – camickr Sep 21 '16 at 15:54
  • @camickr Ah, it's about pack(), OK. – Stefan Reich Sep 21 '16 at 18:15
8

Either create the imageicon up front:

ImageIcon icon = new ImageIcon("image.gif");
table.setValueAt(icon, row, column);

Or you can try overriding the renderer for your icon field:

static class IconRenderer extends DefaultTableCellRenderer {
  public IconRenderer() { super(); }

  public void setValue(Object value) {
    if (value == null) {
      setText("");
    }
    else
    {
      setIcon(value);
    }
}
ayush
  • 14,350
  • 11
  • 53
  • 100
-1

1- add label to jtable ( create class for this)

 class LabelRendar implements TableCellRenderer{

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
      //  throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        return (Component)value;
    }

}

2- code jButton to add image

DefaultTableModel m = (DefaultTableModel) jTable1.getModel();
      jTable1.getColumn("image").setCellRenderer(new LabelRendar());  // call class 
      JLabel lebl=new JLabel("hello");
      lebl.setIcon(new javax.swing.ImageIcon(getClass().getResource("/main/bslogo120.png"))); // NOI18N
          m.addRow(new Object[]{"", "","",lebl});
Shinwar ismail
  • 299
  • 2
  • 9
  • (1-) Don't add components to a TableModel. The model should only contain the data and use a renderer to display the data. – camickr Jun 11 '21 at 14:05
-1

I created my own class that implements TableCellRenderer. I can extend this class from JLabel, but I have preferred to keep it independent and used JLabel 'label' as a class component.

public class GLabel implements TableCellRenderer{
    //The JLabel that is used to display image
    private final JLabel label = new JLabel();  
    
    /**
     * 
     * @param text
     * @param image 
     */
    public GLabel(String text, ImageIcon image) {
        label.setText(text);
        label.setIcon(image);
    }
    
    public GLabel(){}

    public JLabel getLabel() {
        return label;
    }      

    /**
     *
     * @param table the JTable that is asking the renderer to draw; can be null
     * @param value the value of the cell to be rendered. 
     * It is up to the specific renderer to interpret and draw the value. 
     * For example, if value is the string "true", it could be rendered as a string or it could be rendered as a check box that is checked. 
     * null is a valid value
     * @param isSelected true if the cell is to be rendered with the selection highlighted; otherwise false
     * @param hasFocus if true, render cell appropriately. For example, put a special border on the cell, if the cell can be edited, render in the color used to indicate editing
     * @param row the row index of the cell being drawn. When drawing the header, the value of row is -1
     * @param column the column index of the cell being drawn
     * @return 
     */
    @Override
    public Component getTableCellRendererComponent(JTable table,
                                      Object value,
                                      boolean isSelected,
                                      boolean hasFocus,
                                      int row,
                                      int column) {
        GLabel gLabel = (GLabel)value;
        return (Component) gLabel.getLabel();
    }
}

I created a new DefaultTableModel object. I overrides getColumnClass() method to pass appropriate Class at runtime.

private final DefaultTableModel tblmodel = new DefaultTableModel() {        
        /**
         * This method is called by table cell renderer.
         * The method returns class of the cell data. This helps the renderer to display icons and 
         * other graphics in the table.
         */
        @Override
        public Class getColumnClass(int column)
        {
            for(int i = 0; i < tblmodel.getRowCount(); i++)
            {
                //The first valid value of a cell of given column is retrieved.
                if(getValueAt(i,column) != null)
                {
                    return getValueAt(i, column).getClass();
                }
            }
            //if no valid value is found, default renderer is returned.
            return super.getColumnClass(column);
        }
        
    };

I created JTable object using DefaultTableModel I created.

JTable jtable = new JTable(tblmodel);

I set default renderer for GLabel class

jtable.setDefaultRenderer(GLabel.class, new GLabel());

I created new GLabel object.

GLabel glabel = new GLabel("testing", new ImageIcon("c://imagepath"));

Finally, I used addRow(Object[] rowData) method of TableModel to add GLabel to the JTable.

Gaurang
  • 67
  • 8
  • (1-) Don't add components to a TableModel. The model should only contain the data and use a renderer to display the data. – camickr Jun 11 '21 at 14:06