我需要在一个JTable列中显示BufferedImage。我覆盖了JTable方法
@Override
public Class<?> getColumnClass(int column) {
if (column == 1){
return BufferedImage.class;
}
return super.getColumnClass(column);
}
但是我仍然在获取对象的字符串表示而不是图像本身。有人知道我缺少什么吗?
答案 0 :(得分:6)
我将填充需要使用ImageIcons显示图像的列并让getColumnClass()
方法返回Icon.class,然后使用显示Icon的JLabel进行渲染。事实上,我相信DefaultCellRenderer确实是一个JLabel,因此它应该已经知道如何处理Icon。
是的,所有模特的需求都是知道它拥有图标。例如,下面的代码适用于以下程序:
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();
}
});
}
}
答案 1 :(得分:4)
TableCellRenderer
没有默认BufferedImage
,您必须提供一个
创建一个从DefaultTableCellRenderer
扩展的新类。覆盖getTableCellRendererComponent
方法
在此方法中,检查传入的值是否为BufferedImage
,如果是,则创建ImageIcon
的实例,并将BufferedImage
传递给它。
使用单元格渲染setIcon
方法,将新ImageIcon
实例传递给它
使用您的表格实例,使用setDefaultRenderer
方法将单元格渲染器与BufferedImage
类相关联
table.setDefaultRenderer(BufferedImage.class, myInstanceOfBufferedImageCellRenderer)
查看Using Custom Renderers了解详情
添加了示例
因此,我使用自己和气垫船的想法一起举了一个简单的例子。
我个人认为,只要您为每个ImageIcon
创建一次BufferedImage
并维护该引用,Hovercraft的想法将使用更少的资源并更快地使用单元格重新设置器。
您可以让自定义单元格渲染器执行相同操作,但您需要使用WeakHashMap
来保持BufferedImage
和Icon
之间的引用,并且仍然存在有可能永远不会收集有问题的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;
}
}
}