具有两种数据类型的JTable单元

时间:2013-02-03 10:42:25

标签: java swing jtable renderer imageicon

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

还有一些问题:

  1. 如何设置它以使文本替换图像,而不是在图像之后写入文本(即使它不可见);

  2. 如何设置文字颜色,我会使用setForebackground(Color c),但如果我使用它,图片就不会显示。

  3. 是否可以使其与Jlabel一起使用?在线程中设置所需的Jlabel(带图像或文本),修改单元格并设置setValueAt(标签,行,列);

3 个答案:

答案 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.classIcon.class返回正确的班级。可以找到示例here

附录:这是一个基于默认实现来说明原理的最小例子。

附录:当需要返回同一列的不同类时,不确定它是否有效。

如果您确实需要按单元格选择渲染器,请覆盖prepareRenderer(),如图所示here

image

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