Rendering BufferedImage in JTable cell

前端 未结 2 551
半阙折子戏
半阙折子戏 2020-12-07 06:57

I need to display a BufferedImage in one JTable column. I overwrote JTable method

@Override
public Class getColumnClass(int column) {
    if (colum         


        
相关标签:
2条回答
  • 2020-12-07 06:58

    There is no default TableCellRenderer for BufferedImage, you're going to have to supply one

    Create yourself a new class that extends from DefaultTableCellRenderer. Override the getTableCellRendererComponent method

    In this method, check the value been passed in is a BufferedImage, if it is, create a instance of ImageIcon, passing the BufferedImage into it.

    Use the cell renderes setIcon method, passing the new instance of ImageIcon to it

    With your table instance, use the setDefaultRenderer method to associate the cell renderer with the BufferedImage class

    table.setDefaultRenderer(BufferedImage.class, myInstanceOfBufferedImageCellRenderer)
    

    Check out Using Custom Renderers for more info

    Added example

    So a threw a quick example together using both ideas from myself and Hovercraft.

    enter image description here

    My personally feeling is that Hovercraft's idea will use less resources and be quicker then using a cell renenderer, so long as you create a ImageIcon once for each BufferedImage and maintain that reference.

    You could get the custom cell renderer to do the same, but you would need to dabble with WeakHashMaps to maintain a reference between the BufferedImage and Icon and there is still the risk that the BufferedImage in question will never be collected, leaving the Icon reference hanging around.

    If you weren't doing anything special with the BufferedImage in the way of rendering, I would use Hovercraft's suggest, purly from a ease of use and resource management perspective.

    public class BufferedImageTableCellRenderer {
    
        public static void main(String[] args) {
            new BufferedImageTableCellRenderer();
        }
    
        public BufferedImageTableCellRenderer() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    File[] files = new File("some folder some where").listFiles(new FileFilter() {
                        @Override
                        public boolean accept(File pathname) {
                            String name = pathname.getName().toLowerCase();
                            return name.endsWith(".gif") || name.endsWith(".jpg") || name.endsWith(".png");
                        }
                    });
    
                    ImageTableModel model = new ImageTableModel();
                    for (File file : files) {
                        try {
                            model.add(ImageIO.read(file));
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
    
                    JTable table = new JTable(model);
                    table.setRowHeight(100);
                    table.setDefaultRenderer(BufferedImage.class, new BufferedImageCellRenderer());
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new JScrollPane(table));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class BufferedImageCellRenderer extends DefaultTableCellRenderer {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                if (value instanceof BufferedImage) {
                    setIcon(new ImageIcon((BufferedImage)value));
                    setText(null);
                } else {
                    setText("Bad image");
                }
                return this;
            }
        }
    
        public class ImageTableModel extends AbstractTableModel {
    
            private List<BufferedImage> images = new ArrayList<>(25);
            private List<Icon> icons = new ArrayList<>(25);
    
            @Override
            public int getRowCount() {
                return images.size();
            }
    
            public void add(BufferedImage image) {
                images.add(image);
                icons.add(new ImageIcon(image));
                fireTableRowsInserted(images.size() - 1, images.size() - 1);
            }
    
            @Override
            public int getColumnCount() {
                return 2;
            }
    
            @Override
            public Object getValueAt(int rowIndex, int columnIndex) {
                Object value = null;
                switch (columnIndex) {
                    case 0:
                        value = images.get(rowIndex);
                        break;
                    case 1:
                        value = icons.get(rowIndex);
                        break;
                }
                return value;
            }
    
            @Override
            public Class<?> getColumnClass(int columnIndex) {
                Class clazz = String.class;
                switch (columnIndex) {
                    case 0:
                        clazz = BufferedImage.class;
                        break;
                    case 1:
                        clazz = Icon.class;
                        break;
                }
                return clazz;
            }
    
            @Override
            public String getColumnName(int column) {
                String name = null;
                switch (column) {
                    case 0:
                        name = "BufferedImage";
                        break;
                    case 1:
                        name = "Icon";
                        break;
                }
                return name;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-07 07:02

    I'd populate the column that needs to show an image with ImageIcons and have the getColumnClass() method return Icon.class, and then render it with a JLabel that displays the Icon. In fact, I believe that the DefaultCellRenderer really is a JLabel, and so it should already know how to handle Icons.

    Yep, all the model needs is to know that it holds Icons. For example, this code below works in the program below:

      DefaultTableModel model = new DefaultTableModel(COL_NAMES, 0) {
         @Override
         public Class<?> getColumnClass(int column) {
            if (getRowCount() > 0) {
               return getValueAt(0, column).getClass();
            }
    
            return super.getColumnClass(column);
         }
      };
    

    For example:

    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    import javax.imageio.ImageIO;
    import javax.swing.*;
    import javax.swing.table.DefaultTableModel;
    
    public class ImageColumnTest2 {
       public static final String IMAGE_SHEET_PATH = "http://speckycdn.sdm.netdna-cdn.com/"
             + "wp-content/uploads/2010/08/flag_icons_04.jpg";
       public static final String[] COUNTRIES = {
          "Denmark", "China", "Chile", "Canada", "Belgium", "Austria",
          "Argentina", "France", "Malaysina", "Lebanon", "Korea", "Japan",
          "Italy", "Ireland", "India", "Hong Kong", "Greece", "Germany"
       };
       public static final int COLS = 6;
       public static final int ROWS = 3;
       private static final String[] COL_NAMES = {"Country", "Flag"};
    
       private JTable table = new JTable();
       private JScrollPane mainPane = new JScrollPane(table);
    
       public ImageColumnTest2() throws IOException {
          DefaultTableModel model = new DefaultTableModel(COL_NAMES, 0) {
             @Override
             public Class<?> getColumnClass(int column) {
                if (getRowCount() > 0) {
                   return getValueAt(0, column).getClass();
                }
    
                return super.getColumnClass(column);
             }
          };
          URL url = new URL(IMAGE_SHEET_PATH);
          BufferedImage img = ImageIO.read(url);
          int x1 = 15;  // sorry about the magic numbers
          img = img.getSubimage(x1, 0, img.getWidth() - 2 * x1, img.getHeight());
    
          int y1 = 20 ;  // ditto!
          int w = img.getWidth() / COLS;
          int h = img.getHeight() / ROWS;
          for (int row = 0; row < ROWS; row++) {
             int y = (row * img.getHeight()) / ROWS;
             for (int col = 0; col < COLS; col++) {
                int x = (col * img.getWidth()) / COLS;
                BufferedImage subImg = img.getSubimage(x, y, w, h);
    
                subImg = subImg.getSubimage(x1, 0, subImg.getWidth() - 2 * x1, subImg.getHeight() - y1);
    
                ImageIcon icon = new ImageIcon(subImg);
                String country = COUNTRIES[col + row * COLS];
                Object[] rowData = {country, icon};
                model.addRow(rowData);
             }
          }
    
    
          table.setModel(model);
          table.setRowHeight(((ImageIcon)model.getValueAt(0, 1)).getIconHeight());
       }
    
       public JComponent getMainComponent() {
          return mainPane;
       }
    
       private static void createAndShowGui() {
          ImageColumnTest2 imgColumnTest = null;
          try {
             imgColumnTest = new ImageColumnTest2();
          } catch (MalformedURLException e) {
             e.printStackTrace();
             System.exit(-1);
          } catch (IOException e) {
             e.printStackTrace();
             System.exit(-1);
          }
    
          JFrame frame = new JFrame("ImageColumnTest");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(imgColumnTest.getMainComponent());
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    
    0 讨论(0)
提交回复
热议问题