JTable选中行高亮时如何保留显示单元格原有背景颜色
JTable 半透明选中高亮实现方案
现有实现选中单元格时直接用纯不透明的浅灰色替换原单元格背景,会完全覆盖预设的单元格底色,要实现类似Excel选中时既保留原有底色、又清晰显示选中状态的半透明效果,只需要调整单元格渲染器的背景色处理逻辑即可。
效果参考
- 初始自定义单元格背景效果:

- 默认纯不透明选中效果(原有底色被完全遮挡):

- 目标半透明选中效果:

实现要点
- 不要直接给Swing组件设置带Alpha通道的透明背景色,否则会出现重绘残影、脏区问题
- 先计算单元格未选中状态下的自定义背景色,选中状态下将原背景色和半透明高亮色做RGB混合,得到完全不透明的叠加色再设置给渲染组件
- 半透明高亮的Alpha值可根据需求调整,取值范围0-255,数值越小透明效果越强,100-140区间的效果接近Excel的选中表现
完整修改后代码
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellRenderer; class EvenOddRenderer implements TableCellRenderer { public static final DefaultTableCellRenderer DEFAULT_RENDERER = new DefaultTableCellRenderer(); // 半透明选中高亮色,Alpha值120可按需调整 private static final Color SELECT_HIGHLIGHT = new Color(192, 192, 192, 120); /** * 按透明度混合上下两层颜色,返回完全不透明的最终混合色 */ private Color mixColor(Color baseColor, Color overlayColor) { if (baseColor == null) baseColor = Color.WHITE; float alphaRatio = overlayColor.getAlpha() / 255f; int red = (int) (overlayColor.getRed() * alphaRatio + baseColor.getRed() * (1 - alphaRatio)); int green = (int) (overlayColor.getGreen() * alphaRatio + baseColor.getGreen() * (1 - alphaRatio)); int blue = (int) (overlayColor.getBlue() * alphaRatio + baseColor.getBlue() * (1 - alphaRatio)); return new Color(red, green, blue); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component renderer = DEFAULT_RENDERER.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); Color foreground = Color.red; Color background = Color.WHITE; // 先计算未选中状态下的自定义单元格背景 if (column == 1 && row == 0) { background = Color.GREEN; } else if (column == 1 && row == 1) { background = Color.CYAN; } else if (column == 1 && row == 2) { background = Color.ORANGE; } else if (column == 2) { background = Color.YELLOW; } // 选中状态下叠加半透明高亮,而不是直接替换背景 if (isSelected) { background = mixColor(background, SELECT_HIGHLIGHT); } renderer.setForeground(foreground); renderer.setBackground(background); return renderer; } } public class CellColorTransparency { public static void main(String args[]) { final Object rowData[][] = { {"1", "one", "I"}, {"2", "two", "II"}, {"3", "three", "III"}}; final String columnNames[] = {"#", "English", "Roman"}; final JTable table = new JTable(rowData, columnNames); JScrollPane scrollPane = new JScrollPane(table); table.setDefaultRenderer(Object.class, new EvenOddRenderer()); JFrame frame = new JFrame("Color Test Table"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(scrollPane, BorderLayout.CENTER); frame.setSize(300, 150); frame.setVisible(true); } }
运行上述代码即可实现选中时半透明叠加原有单元格背景色的效果,不会出现原有底色被完全覆盖的问题。
内容的提问来源于stack exchange,提问作者Unhandled Exception
相关产品推荐
相关产品推荐

