我在JTable中有一个列应该显示两种类型:String OR ImageIcon,而不是两者。该列中的每个单元都有自己的线程来计算数据。在开始时,我向每个单元格放置一个图像(如等待徽标),然后用一串计算数据替换(不附加)图像。我试图扩展默认的TableCell渲染器,但它显示像对象地址(javax.swing.ImageIcon@342 ...)的图像,然后替换为字符串。另一种变体,它正确显示图像,但用空字符串替换它(或者它不可见?)。
如何设置,以便表格根据类型正确显示单元格内容?
这就是我现在所拥有的:
class IconAndStringRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 3606788739290618405L;
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 Icon) {
setIcon((Icon) value);
setText("");
}
return this;
}
}
这是JTable:
table = new JTable(model){
private static final long serialVersionUID = 8058795799817761161L;
public Class<?> getColumnClass(int column) {
if (column == TARGET_COLUMN)
return ImageIcon.class;
else
return super.getColumnClass(column);
}
};
还有一些问题:
如何设置它以使文本替换图像,而不是在图像之后写入文本(即使它不可见);
如何设置文字颜色,我会使用setForebackground(Color c),但如果我使用它,图片就不会显示。
是否可以使其与Jlabel一起使用?在线程中设置所需的Jlabel(带图像或文本),修改单元格并设置setValueAt(标签,行,列);
答案 0 :(得分:2)
您需要一个可以理解您使用的两种类型的自定义渲染器。
例如
public class IconAndStringRenderer extends DefaultTableCellRenderer {
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 Icon) {
setText("");
setIcon((Icon) value);
}
return this;
}
}
尝试将此类设置为列渲染器
答案 1 :(得分:2)
default renderer知道如何显示字符串和图标。您所要做的就是确保TableModel
分别从getColumnClass()
,String.class
和Icon.class
返回正确的班级。可以找到示例here。
附录:这是一个基于默认实现来说明原理的最小例子。
附录:当需要返回同一列的不同类时,不确定它是否有效。
如果您确实需要按单元格选择渲染器,请覆盖prepareRenderer()
,如图所示here。
import java.awt.EventQueue;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
/** @see https://stackoverflow.com/a/14672312/230513 */
public class Test {
private static final Icon YES = UIManager.getIcon("InternalFrame.maximizeIcon");
private static final Icon NO = UIManager.getIcon("InternalFrame.closeIcon");
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model = new DefaultTableModel(
new Object[]{"Name", "Icon"}, 0) {
@Override
public Class<?> getColumnClass(int col) {
if (col == 1) {
return Icon.class;
} else {
return super.getColumnClass(col);
}
}
};
model.addRow(new Object[]{"One", YES});
model.addRow(new Object[]{"Two", NO});
final JTable table = new JTable(model);
table.setRowHeight(YES.getIconHeight() +2);
f.add(table);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Test().display();
}
});
}
}
答案 2 :(得分:2)
要利用默认渲染器,您可以覆盖JTable的getCellRenderer(...)方法以返回相应的渲染器。类似的东西:
public TableCellRenderer getCellRenderer(int row, int column)
{
int modelColumn = convertColumnIndexToModel(column);
if (modelColumn == ???)
{
Class rowClass = getModel().getValueAt(row, modelColumn).getClass();
return getDefaultRenderer( rowClass );
}
else
return super.getCellRenderer(row, column);
}