3

我试图能够在 JTable 中为单独的单元格着色,但到目前为止我只能在整个列上应用 TableCellRenderer,这显然会出现故障。我有一个自定义的 JTable:

public class JColorTable extends JTable{
  (...)
  public void setCellColor(int col, int row, Color newColor) {
    getColumnModel().getColumn(col).setCellRenderer(new ColorField(col, row, newColor, background));
    repaint();
  }
}

ColorField 看起来像这样:

class ColorField extends DefaultTableCellRenderer {

    (...))

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {

        JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

        if (row == newRow && column == newCol) {
            l.setBackground(Color.red);
        } else {
            l.setBackground(defaultColor);
        }

        return l;
    }
}

当我在一列中有一个彩色单元格时,这就像一个魅力,但是当我尝试为该列中的另一个单元格着色时,前一个被删除(由于 ColorField 中的条件不适用于上一列)。

有没有办法只将 ColorField 应用于单个单元格,而不是整个列?如果是这样,怎么做?恐怕我没有找到合适的东西。

4

4 回答 4

3

就个人而言,我会避免任何需要您扩展JTable. 主要原因是它降低了代码的可移植性,并将渲染器与JTable. 它可能适合您的需求,但就个人而言,我总是试图看到更大的图景/潜力/重用。

请记住,单元格渲染器绑定到表格列。本质上,它并不意味着能够逐个单元地提供自定义渲染。但是,您可以根据渲染器中的一系列条件为每个单元格提供渲染逻辑。

我可能会将某种条件/格式引擎放在一起,您可以使用它来传递单元格值和坐标,然后根据引擎的特定实现的需要做出决定。

class ColorField 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);

        // CellFormat is an object you create to hold the various aspects
        // of the cell format
        // You could also pass in the selected and focused flags if you
        // needed them...
        // getFormatEngine is a method you would write to provide
        // to gain access to the format engine
        CellFormat format = getFormatEngine().getFormatFor(value, row, column);
        setBackground(format.getBackground());
        setForeground(format.getForeground());
        setFont(format.getFont());
        // Any other properties you may wish to effect...

        return this;
    }
}

FormatEngine将是决定如何最好地格式化给定单元格的基础。它也应该能够提供“默认”格式

这意味着您可以为特定的单元格类型设计一个“默认”渲染器,但能够根据您的需要提供自定义渲染,而无需多个if语句或扩展基本渲染

这也是条件格式化引擎的基础,您可以在其中针对给定值应用一系列条件并根据结果返回适当的格式

于 2013-05-06T22:22:10.900 回答
3

JTable有一个getCellRenderer()可以覆盖的方法。当单元格需要渲染并根据行和列返回一个时调用它。

JTable需要记录每个单元格使用哪个渲染器(按行和列)。二维数组可以做到这一点,或者Map键是 X,Y 值。

添加一个方法来在特定单元格(按行和列)上设置渲染器,然后就可以了。

class MyTable extends JTable {

    // all the other JTable stuff goes here too ...

    public TableCellRenderer getCellRenderer(int row, int column) {
        TableCellRenderer myRenderer = getCustomRenderer(row, column);
        if (myRenderer != null) {
            return myRenderer;
        }
        // else...
        return super.getCellRenderer(row, column);
    }

    private Map<Integer, Map<Integer, TableCellRenderer>> rendererMap = new ...;

    public void setCustomRenderer(int row, int column, TableCellRenderer renderer) {
        Map<Integer, TableCellRenderer> m1 = rendererMap.get(row);
        if (m1 == null) {
            m1 = new ...;
            rendererMap.put(row, m1);
        }
        m1.put(column, renderer);
    }

    public TableCellRenderer getCustomRenderer(int row, int column) {
        Map<Integer, TableCellRenderer> m1 = rendererMap.get(row);
        if (m1 == null) {
            return null;
        }
        return m1.get(column);
    }
}

默认版本getTableCellRenderer使用列上设置的渲染器,如果有,则使用基于单元格内容的类的渲染器。Object在许多情况下,默认单元格内容是。这取决于所TableModel使用的。

于 2013-05-06T21:03:20.210 回答
0

您需要为列中的每个单元格提供一些颜色信息。此信息可能驻留在值中:

class CellValue {
    Color getBackgroundColor() { ... }
    String getCellContent() { ... }
}

您的getTableCellRendererComponent()方法可能如下所示:

CellValue cellValue = (CellValue) value;
Color bgColor = cellValue.getBackgroundColor();
String text = cellValue.getCellContent();

JLabel l = (JLabel) super.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column);

l.setBackground(bgColor);

...

当然,您必须调整您的 TableModel 以存储 CellValue 实例。

于 2013-05-06T21:04:35.793 回答
0

我相信实现这一点的正确方法是通过ColorHighlighter。这是在文档中说的。这是SO 中的一个相关问题

注意:如果表允许排序,则必须实现相应的 ComponentAdapter,并使用其 dapter.convertRowIndexToModel

于 2015-05-25T14:07:45.167 回答