首页 > 解决方案 > 在运行时设置 JTable 行的颜色

问题描述

我的 Java 8 小程序连接到 SQL 数据库,并在JTable包含两列的 a 中显示“选择”语句的结果:

如果第 1 行/ColumnA 中的字符串与第 0 行/ColumnA 中的字符串不同,我想给第 1 行一个灰色背景色(以标记“新”数据的开始),其他行应该使用默认白色。

创建表的代码:

JTable myTable = new JTable();
myTable.setSelectionModel(new ToggleListSelectionModel()); //custom selection model
myTable.setModel(new DefaultTableModel(
    new Object[][] {
    },
    new String[] {
        "ColumnA", "ColumnB"
    }
));

获取数据并填写表格:

Statement stat = connection.createStatement();
ResultSet rs = stat.executeQuery(someSelectStatement);
Object[] row = null;

while(rs.next()) {  
    int columns = rs.getMetaData().getColumnCount();    
    row = new Object[columns];

    for (int i=1; i<=columns; i++) {
        row[i - 1] = rs.getObject(i);
    }

    //TODO: Set color of row according to data in "ColumnA" of previous row
    ((DefaultTableModel) myTable.getModel()).insertRow(rs.getRow()-1,row); //Add new row with the ResultSet's content
    //Get String data of ColumnA for this specific row with e.g. "(String) row[0]"
}

rs.close();
stat.close();

从我目前发现的情况来看,我必须使用自定义TableModel而不是DefaultTableModel我在开始时设置的,但我该如何使用它呢?我发现的所有东西都使用固定检查,例如

如果单元格中的内容是“购买”,则将背景颜色设置为“绿色”

(例如herehere)但在我的情况下,我对创建表时的内容一无所知,因为它是在运行时填充/行添加的。

我也找到了这个答案,但是问题的作者读取了数据,然后更改了模型,然后才填充表格,而我逐行填充表格(直接在读取行的内容之后)。

我的问题:我知道如何将单元格的内容与上一行中单元格的内容进行比较,但是如何在运行时设置该行的背景颜色?

编辑:

这是一些用于填写表格的 MRE 代码。请注意:如果您发布有关如何完成我想做的事情的建议,请记住我正在使用数据库和ResultSet(参见上面的代码),而不是预定义的数据(参见下面的代码)!

JTable myTable = new JTable();
myTable.setSelectionModel(new ToggleListSelectionModel()); //custom selection model
myTable.setModel(new DefaultTableModel(
    new Object[][] {
        {"1000", 123},
        {"1000", 234}, 
        {"1001", 123},
        {"1002", 123},
        {"1002", 234},
        {"1002", 345},
        {"1003", 123},
        {"1003", 234}
    },
    new String[] {
        "ColumnA", "ColumnB"
    }
));

结果:

在此处输入图像描述

所需结果(每个新“A 列”值的灰色背景):

在此处输入图像描述

替代结果(替代标记组的所有行):

在此处输入图像描述

标签: javaswingjtable

解决方案


table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
    @Override
    public Component getTableCellRendererComponent(JTable table,
                                  Object value,
                                  boolean isSelected,
                                  boolean hasFocus,
                                  int row,
                                  int column) {
        Component comp = super.getTableCellRendererComponent(table,
                value, isSelected, hasFocus, row, column);
        if(!isSelected) { //Important check, see comment below!
            boolean levelBreak = row == 0;
            if (!levelBreak) {
                Object prior = table.getValueAt(row - 1, 0);
                Object current = table.getValueAt(row, 0);
                levelBreak = !prior.equals(current);
            }
            comp.setBackground(levelBreak ? Color.BLUE : Color.WHITE);
        }
        return comp;
    }
});

由于渲染器/渲染器组件对所有表格单元格重复使用,因此必须为所有情况设置背景。

一般来说,JTable 的 TabelModel 比 JTable 的 getValueAt 更适合获取值,但显然您既不排序行也不重新排列列。


对于可能安装的较旧渲染器

class MyCellRenderer extends DefaultTableCellRenderer {

    private final TableCellRenderer old;

    MyCellRenderer(TableCellRenderer old) {
        this.old = old;
    }

    @Override
    public Component getTableCellRendererComponent(JTable table,
                                  Object value,
                                  boolean isSelected,
                                  boolean hasFocus,
                                  int row,
                                  int column) {
        boolean levelBreak = row == 0;
        if (!levelBreak) {
            Object prior = table.getValueAt(row - 1, 0);
            Object current = table.getValueAt(row, 0);
            levelBreak = !prior.equals(current);
        }
        Component comp;
        if (old != null) {
            comp = old.getTableCellRendererComponent(table,
                value, isSelected, hasFocus, row, column);
        } else {
            comp = super.getTableCellRendererComponent(table,
                value, isSelected, hasFocus, row, column);
        }
        comp.setBackground(levelBreak ? Color.BLUE : Color.WHITE);
        return comp;
    }
}

table.setDefaultRenderer(Object.class, new MyCellRenderer(table.getDefaultRenderer(Object.class));

推荐阅读