1

I am trying to use JTable for showing my personnel list with each picture dedicated to each person. I want to show these images in a JTable cell. I achieved showing images from directory with custom cell renderer. This cell renderer returns the label which has icon via the method new ImageIcon(). Every time scrolling happens in my JTable, I guess this renderer works and creates new images from the directory. So this makes RAM explode and glitches in the images. I read all of the questions related to this problem, however I could not find an efficient way to solve it. An approach to this problem would be much appreciated.

My renderer looks like:

public class ImageCellRenderer extends DefaultTableCellRenderer{
 JLabel lbl=new JLabel();
 public Component getTableCellRendererComponent(defaultparameters){
 ImageIcon imageIcon=new ImageIcon(getClass().getResource("path to directory"+table.getModel().getValueAt(row,column).toString+".jpg"));
 """
 Some code to turn image icon to scaled version
 """
 lbl.setIcon(imageIcon)
 return lbl;

 }

}
Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
D.small
  • 11
  • 3
  • What does your custom renderer look like? Does your table model create images and keep them in memory for when they are needed again, or do you recreate them constantly? Show some sample code. – Riaan Nel Feb 24 '20 at 11:47
  • When first initialized i add my personnel list to my model.After that i set my column to show image, new cell renderer. My table at that row has unique id for the name of the image file.Image file is rendered with my custom cell renderer coded above. – D.small Feb 24 '20 at 12:11
  • 1) There is no need for a custom renderer. You override the `getColumnClass(…)` method to return Icon for the column and the table will use its default Icon renderer 2) An ImageIcon is stored in the table model. Therefore the image is only ever read once when you initially load the data into the model and the memory usage will not grow. See: https://stackoverflow.com/questions/5614875/how-to-set-icon-in-a-column-of-jtable/5615516#5615516 for a basic example. – camickr Feb 24 '20 at 15:26
  • I tried your method too.However,when scrolling in my table, i can't get rid of images' glitching after 8th row. So i think i need an another approach for solving the problem. Maybe the problem is related with my computer and hardware? – D.small Feb 25 '20 at 07:59

1 Answers1

0

Use the same ImageIcon, I guess.

Something like:

// Note: Probably don't use `DefaultTableCellRenderer`,
//    unless you are using the `JLabel` part of that.
public class ImageCellRenderer extends DefaultTableCellRenderer {
    private final JLabel label = new JLabel();
    private final Map<String,ImageIcon> images = new HashMap<>();
    public Component getTableCellRendererComponent(defaultparameters) {
        ImageIcon imageIcon = images.computeIfAbsent(
            value.toString(),
            // No need to look value up again. Delete this:
            //table.getModel().getValueAt(row,column).toString(),
            cell -> {
                ImageIcon newImage = new ImageIcon(
                    getClass().getResource("path to directory"+cell+".jpg")
                );
                """
                Some code to turn image icon to scaled version
                """
                return newIcon;
            }
        );
        lbl.setIcon(imageIcon)
        return lbl;
    }
}

(Whether you want to share the "cache" (leek) between renderers and cache eviction policy is left as an exercise.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • I tried this code and it works indeed.However, the same problem continues with cache problem. That was the main problem i could not solve.In some of the questions they mentioned publish/subscribe method for making this process cheaper.But I have no idea how to apply though i searched that method. Any help would be much appreciated before i go crazy:) – D.small Feb 24 '20 at 12:51
  • @D.small What do you mean by "cache problem"? You've not recreating the renderer every repaint, are you? – Tom Hawtin - tackline Feb 24 '20 at 12:55
  • I was using an MVC pattern and put my renderer setting code into Controller's constructor method and i was using method setCellRenderer(new ImageCellRenderer). Can this be a problem? – D.small Feb 24 '20 at 13:16
  • A breakpoint or "printf" in the constructor of `ImageCellRenderer` would be the easiest way to tell. (It doesn't have an explicit construction an *instance initialiser* would be the shortest way to do it.) – Tom Hawtin - tackline Feb 24 '20 at 13:19
  • I put a breakpoint in that line and saw that it ran only once, maybe the problem is that i have around 2500 jpg files and finding that file with row id could be the problem. – D.small Feb 24 '20 at 13:26
  • `new JLabel()` should be removed. The DefaultTableCellRenderer is itself a JLabel. – VGR Feb 24 '20 at 15:17
  • @camickr There's code in Swing which does I/O on the EDT. Get it working first. I assume that's what you're getting at - because it isn't going to make any difference if you just reorder the code. – Tom Hawtin - tackline Feb 24 '20 at 16:00
  • @camickr I don't see why it would make any difference, if you're still proposing to do it on the EDT. I prefer a very thin renderer, but I think that's an orthogonal issue. – Tom Hawtin - tackline Feb 24 '20 at 20:08