2013-02-10 89 views
0

我需要在一個JTable列中顯示BufferedImage。我改寫的JTable方法在JTable單元中渲染BufferedImage

@Override 
public Class<?> getColumnClass(int column) { 
    if (column == 1){ 
     return BufferedImage.class; 
    } 
    return super.getColumnClass(column); 
} 

但我仍然獲得了對象,而不是像itself.Does人的字符串表示有想法,我缺少的是什麼?

+0

我認爲這種聯繫解決它倒過來。 – MiSu 2013-02-10 01:00:28

回答

4

沒有默認TableCellRendererBufferedImage,你將不得不提供一個

創建自己從DefaultTableCellRenderer延伸的新類。重寫getTableCellRendererComponent方法

在這種方法中,檢查值中獲得通過是一個BufferedImage,如果是,創建一個ImageIcon例如,傳遞BufferedImage進去。

使用電池renderes setIcon方法,傳遞的ImageIcon的實例給它

隨着你的表實例,使用setDefaultRenderer方法將細胞渲染與BufferedImage

table.setDefaultRenderer(BufferedImage.class, myInstanceOfBufferedImageCellRenderer) 

退房關聯Using Custom Renderers獲取更多信息

已添加示例

因此,我用自己和氣墊船的想法一起舉了一個快速的例子。

enter image description here

我個人的感覺是,當你創建一個ImageIcon一次爲每個BufferedImage並維持基準氣墊船的想法將使用更少的資源,更快然後用細胞renenderer,這麼久。

你可以得到自定義單元格渲染器做同樣的,但你需要WeakHashMap s到涉足保持BufferedImageIcon之間的引用,仍然存在有問題的BufferedImage將永遠不會被收集的風險,留下了Icon參考。

如果您在渲染的方式上沒有對BufferedImage做任何特殊處理,我會使用Hovercraft的建議,純粹是從易用性和資源管理的角度出發。

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; 
     } 
    } 
} 
6

我填充,需要顯示與ImageIcons的圖像,並有getColumnClass()方法返回Icon.class,然後用一個顯示圖標的JLabel使其列。實際上,我相信DefaultCellRenderer確實是一個JLabel,所以它應該已經知道如何處理圖標。

是的,所有模型的需要是知道它擁有圖標。例如,該代碼如下工作在下面的程序:

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); 
    } 
    }; 

例如:

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

對於可能使用較少資源的解決方案+1# – MadProgrammer 2013-02-10 02:15:29

+0

@MadProgrammer:謝謝。和1+也是你的! – 2013-02-10 02:16:04

+1

無關緊要的問題:只有當內容!= null和所有單元格的類型完全相同時,纔會詢問其類的值。這是 - 可以說的,但是這就是挑剔的全部內容:-) - 在無效實現的邊界上很難,因爲返回的類對於空對齊或填充模型應該是相同的 – kleopatra 2013-02-10 11:23:00