You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swing表格列渲染关联另一列值的优化实现方案问询

Swing表格跨列依赖渲染的优雅实现方案

针对Swing表格中某一列渲染(前景色、背景色)依赖另一列值的需求,我们可以通过枚举+策略模式+自定义数据模型的组合方案,规避过程式代码、强制类型转换与不合理依赖,实现更易维护、符合开闭原则的代码结构。

核心设计思路

  1. 用枚举替代硬编码的条件字符串,避免拼写错误与松散的字符串判断
  2. 为每种条件定义独立的渲染策略类,将颜色逻辑与业务数据解耦
  3. 自定义TableModel封装业务数据,提供安全的行数据访问方式,避免依赖列索引

代码实现步骤

1. 定义业务数据模型与枚举

首先封装业务数据,用枚举表示条件类型:

// 业务数据类,封装一行的所有信息
public class DataEntry {
    private Level level;
    private int value;

    public DataEntry(Level level, int value) {
        this.level = level;
        this.value = value;
    }

    public Level getLevel() { return level; }
    public int getValue() { return value; }
}

// 枚举替代硬编码的条件字符串,绑定对应的渲染策略
public enum Level {
    HIGH(new HighLevelStrategy()),
    LOW(new LowLevelStrategy()),
    MEDIUM(new MediumLevelStrategy());

    private final RenderStrategy strategy;

    Level(RenderStrategy strategy) {
        this.strategy = strategy;
    }

    public RenderStrategy getRenderStrategy() {
        return strategy;
    }
}

2. 定义渲染策略接口与实现

创建统一的渲染策略接口,每种条件对应一个实现类:

// 渲染策略接口,定义颜色获取方法
public interface RenderStrategy {
    Color getBackground(boolean isSelected);
    Color getForeground(boolean isSelected);
}

// High级别对应的渲染策略
public class HighLevelStrategy implements RenderStrategy {
    @Override
    public Color getBackground(boolean isSelected) {
        return isSelected ? Color.RED.darker() : Color.RED;
    }

    @Override
    public Color getForeground(boolean isSelected) {
        return Color.WHITE;
    }
}

// Low级别对应的渲染策略
public class LowLevelStrategy implements RenderStrategy {
    @Override
    public Color getBackground(boolean isSelected) {
        return isSelected ? Color.GREEN.darker() : Color.GREEN;
    }

    @Override
    public Color getForeground(boolean isSelected) {
        return Color.BLACK;
    }
}

// Medium级别对应的渲染策略
public class MediumLevelStrategy implements RenderStrategy {
    @Override
    public Color getBackground(boolean isSelected) {
        return isSelected ? Color.YELLOW.darker() : Color.YELLOW;
    }

    @Override
    public Color getForeground(boolean isSelected) {
        return Color.BLACK;
    }
}

// 默认策略,处理未定义的条件
public class DefaultStrategy implements RenderStrategy {
    @Override
    public Color getBackground(boolean isSelected) {
        return isSelected ? Color.GRAY : Color.WHITE;
    }

    @Override
    public Color getForeground(boolean isSelected) {
        return isSelected ? Color.WHITE : Color.BLACK;
    }
}

3. 自定义TableModel

自定义模型封装数据,提供安全的行数据访问,避免渲染器直接依赖列索引:

public class CustomTableModel extends AbstractTableModel {
    private final List<DataEntry> data = new ArrayList<>();
    private final String[] columnNames = {"Condition", "Value"};

    @Override
    public int getRowCount() {
        return data.size();
    }

    @Override
    public int getColumnCount() {
        return columnNames.length;
    }

    @Override
    public String getColumnName(int column) {
        return columnNames[column];
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        DataEntry entry = data.get(rowIndex);
        return switch (columnIndex) {
            case 0 -> entry.getLevel().name();
            case 1 -> entry.getValue();
            default -> null;
        };
    }

    // 提供直接获取整行业务对象的方法
    public DataEntry getEntryAt(int row) {
        return data.get(row);
    }

    public void addEntry(DataEntry entry) {
        data.add(entry);
        fireTableRowsInserted(data.size() - 1, data.size() - 1);
    }
}

4. 实现自定义单元格渲染器

渲染器通过自定义模型获取业务对象,直接调用对应策略获取颜色,无需过程式判断:

public class ValueCellRenderer 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);
        
        // 从自定义模型获取业务对象,避免依赖列索引与强制类型转换
        CustomTableModel model = (CustomTableModel) table.getModel();
        DataEntry entry = model.getEntryAt(row);
        RenderStrategy strategy = entry.getLevel().getRenderStrategy();

        this.setBackground(strategy.getBackground(isSelected));
        this.setForeground(strategy.getForeground(isSelected));

        return this;
    }
}

5. 主程序使用示例

public class ElegantTableRendererExample {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("优雅的表格渲染示例");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(600, 400);

            CustomTableModel model = new CustomTableModel();
            model.addEntry(new DataEntry(Level.HIGH, 100));
            model.addEntry(new DataEntry(Level.LOW, 20));
            model.addEntry(new DataEntry(Level.MEDIUM, 50));
            model.addEntry(new DataEntry(Level.HIGH, 80));
            model.addEntry(new DataEntry(Level.LOW, 10));

            JTable table = new JTable(model);
            table.getColumnModel().getColumn(1).setCellRenderer(new ValueCellRenderer());

            frame.add(new JScrollPane(table));
            frame.setVisible(true);
        });
    }
}

方案优势

  • 无过程式判断:用枚举+策略模式替代if-else/switch,新增条件只需扩展枚举与策略类,符合开闭原则
  • 避免强制类型转换:通过自定义模型直接获取业务对象,无需从表格单元格取数据后强制转换
  • 减少不合理依赖:不再硬编码列索引,枚举替代字符串避免拼写错误,渲染逻辑与业务数据解耦
  • 易维护扩展:修改颜色样式只需调整对应策略类,新增业务状态无需改动原有渲染逻辑

内容的提问来源于stack exchange,提问作者Heneh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:50:02