JTable 单元格渲染器使用其他单元格背景设置背景

JTable cell renderer set backround using other cells background

我有一个 JTable 自定义 cell renderer 以在有新章节在线时突出显示该单元格。

默认TableCellRenderer:

static class CustomRenderer extends DefaultTableCellRenderer {

    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

        double valueAt = (double) table.getValueAt(row, column);
        double compareValue = (double) table.getValueAt(row, column - 1);
        if (compareValue < valueAt) {
            cellComponent.setBackground(Color.green);
        } else {
            Component tableCellRendererComponent = super.getTableCellRendererComponent(table, compareValue, isSelected, hasFocus, row, column - 1);
            // Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column - 1);
            // Component tableCellRendererComponent = super.getTableCellRendererComponent(table, valueAt, isSelected, hasFocus, row, column - 1);
            Color background = tableCellRendererComponent.getBackground();
            cellComponent.setBackground(background);
        }

        return cellComponent;
    }
}

Table 型号:

private String[] columnsGetNewest = {"Current Chapter", "Chapter Online"};
private DefaultTableModel dataModelGetNewest = new DefaultTableModel(columnsGetNewest, 0);

它的应用使用:

tableGetNewest.setModel(dataModelGetNewest);
TableColumn column = tableGetNewest.getColumnModel().getColumn(1);
column.setCellRenderer(new CustomRenderer());

想要的结果:

但由于某些原因,它没有按预期工作:

代码进入 else 分支时似乎可以正常工作。

如果我注释掉 //cellComponent.setBackground(Color.green); 结果如下:

我的代码有什么问题?我怎样才能得到想要的结果?

如果我没理解错的话,您正试图将 Green 右列中比左列中的单元格具有更高值的所有单元格。如果我错了,请纠正。

问题出在您的 TableCellRenderer 上。在以下部分:

if (compareValue < valueAt) {
    cellComponent.setBackground(Color.green);
} else {
    Component tableCellRendererComponent = super.getTableCellRendererComponent(table, compareValue, isSelected, hasFocus, row, column - 1);
    // Component tableCellRendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column - 1);
    // Component tableCellRendererComponent = super.getTableCellRendererComponent(table, valueAt, isSelected, hasFocus, row, column - 1);
    Color background = tableCellRendererComponent.getBackground();
    cellComponent.setBackground(background);
}

我认为解释你做错了什么的最好方法是举个例子。假设在左列中右边的值高于左边的值,所以你的 if 发生并且 renderer 的背景变成 green。现在,让我们渲染第 2 行。右边的值小于左边的值,因此 if 不会发生。你猜怎么着?您在前一行渲染中将其设为绿色,因此它保持 green。这就是为什么他们一直保持绿色。如果你把它转一次,你不恢复它,它会留给其他人。

现在,您正在尝试恢复背景super.getTableCellRendererComponent(table, valueAt, isSelected, hasFocus, row, column - 1);。这是错误的,因为这个方法不是简单的 getter。它还对 table(渲染器)进行了更改。为另一个 row/column 值调用此方法将不起作用。

为了使其正常工作,您必须根据来自 DefaultTableCellRenderer 的默认值恢复它。一个完整的例子:

public class Example extends JFrame {
    private static final long serialVersionUID = 811854316682851407L;
    private static final String[] COLUMNS = { "Current Chapter", "Chapter Online" };

    public Example() {
        super("test");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        JTable table = new JTable(data(), COLUMNS);
        table.getColumnModel().getColumn(1).setCellRenderer(new DefaultTableCellRenderer() {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
                    int column) {
                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                if (c instanceof JLabel) {
                    JLabel renderer = (JLabel) c;
                    int valueAt = (int) table.getValueAt(row, column);
                    int compareValue = (int) table.getValueAt(row, column - 1);
                    if (compareValue < valueAt) {
                        renderer.setBackground(Color.GREEN);
                    } else {
                        if (isSelected)
                            renderer.setBackground(table.getSelectionBackground());
                        else {
                            renderer.setBackground(table.getBackground());
                        }
                    }
                }
                return c;
            }
        });
        JScrollPane sp = new JScrollPane(table);
        add(sp);
        pack();
        setLocationRelativeTo(null);
    }

    private Object[][] data() {
        Object[][] data = { { 113, 444 }, { 233, 555 }, { 110, 92 }, { 55, 66 }, { 123, 603 }, { 412, 120 }, };
        return data;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Example().setVisible(true));
    }
}

预览: