JTable重复数据单元格渲染:默认颜色重置异常问题
问题:JTable非重复单元格无法重置默认背景色
在Java Swing的JTable中展示齿轮比数值,数据存在重复项,需为每组重复单元格设置不同背景色(重复组包含2-4个单元格)。已通过ArrayList<DuplicateValues>存储重复项的行列位置及对应RGB背景、前景色,并传入自定义单元格渲染器NumberCellRenderer。目前遇到的核心问题:非重复数据的单元格无法重置为默认白背景黑字体,渲染结果异常(如部分非重复单元格继承其他单元格的颜色)。
DuplicateValues类定义
private Double ratio; private int row; private int col; private int backgroundRed; private int backgroundGreen; private int backgroundBlue; private int foregroundRed; private int foregroundGreen; private int foregroundBlue;
当前存在问题的NumberCellRenderer代码
public class NumberCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; private JLabel label; private DecimalFormat numberFormat = new DecimalFormat("#0.000"); private List<DuplicateValues> duplicateValues = new ArrayList<>(); private String text; public NumberCellRenderer (List<DuplicateValues> duplicateValues) { this.duplicateValues = duplicateValues; } @Override public JLabel getTableCellRendererComponent(JTable jTable, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component c = super.getTableCellRendererComponent(jTable, value, isSelected, hasFocus, row, column); if (c instanceof JLabel && value instanceof Number) { label = (JLabel) c; label.setHorizontalAlignment(JLabel.CENTER); Number num = (Number) value; text = numberFormat.format(num); label.setText(text); } for(int i=0; i<duplicateValues.size(); i++) { // if(duplicateValues.get(i).getRatio() == Double.parseDouble(value.toString())) if(row == duplicateValues.get(i).getRow() && column == duplicateValues.get(i).getCol()) { label.setBackground(new Color(duplicateValues.get(i).getBackgroundRed(), duplicateValues.get(i).getBackgroundGreen(), duplicateValues.get(i).getBackgroundBlue())); label.setForeground(new Color(duplicateValues.get(i).getForegroundRed(), duplicateValues.get(i).getForegroundGreen(), duplicateValues.get(i).getForegroundBlue())); } else { label.setBackground(getBackground()); label.setForeground(getForeground()); } } return label; } }
解决方案
问题根源在于遍历重复项的逻辑:每次循环遇到不匹配的单元格就重置默认颜色,导致重复单元格的自定义颜色会被后续不匹配的循环项覆盖,同时非重复单元格的状态也会因为多次重置出现异常。
修改后的渲染器代码:
public class NumberCellRenderer extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; private DecimalFormat numberFormat = new DecimalFormat("#0.000"); private List<DuplicateValues> duplicateValues; public NumberCellRenderer(List<DuplicateValues> duplicateValues) { this.duplicateValues = duplicateValues; // 统一设置默认对齐方式,避免重复操作 setHorizontalAlignment(JLabel.CENTER); } @Override public Component getTableCellRendererComponent(JTable jTable, Object value, boolean isSelected, boolean hasFocus, int row, int column) { // 调用父类方法初始化组件默认状态 super.getTableCellRendererComponent(jTable, value, isSelected, hasFocus, row, column); // 格式化数值显示 if (value instanceof Number) { Number num = (Number) value; setText(numberFormat.format(num)); } // 先设置默认样式:非重复单元格直接使用表格默认颜色 setBackground(jTable.getBackground()); setForeground(jTable.getForeground()); // 遍历重复项,仅为匹配的单元格设置自定义颜色 for (DuplicateValues dv : duplicateValues) { if (dv.getRow() == row && dv.getCol() == column) { setBackground(new Color(dv.getBackgroundRed(), dv.getBackgroundGreen(), dv.getBackgroundBlue())); setForeground(new Color(dv.getForegroundRed(), dv.getForegroundGreen(), dv.getForegroundBlue())); // 找到匹配项后跳出循环,减少无效遍历 break; } } return this; } }
关键优化点
- 先设置默认状态:确保所有单元格初始为表格默认样式,非重复单元格无需额外处理。
- 遍历逻辑调整:仅在找到匹配的重复项时才覆盖颜色,避免后续循环重置已设置的自定义样式。
- 简化代码结构:利用
DefaultTableCellRenderer本身是JLabel子类的特性,直接操作this,无需额外维护label变量。 - 使用表格默认颜色:通过
jTable.getBackground()/getForeground()获取全局默认样式,保证和表格整体风格一致。
内容的提问来源于stack exchange,提问作者user5991980
相关产品推荐
相关产品推荐

