
本文介绍两种在 JTable 的 TableCellRenderer 中实现「单元格内部分文字着色」的方法:一种是基于 HTML 标签的轻量级方案(推荐初学者使用),另一种是自定义 JComponent 重写 paintComponent 的高性能方案,并提供可直接运行的代码示例与适配建议。
本文介绍两种在 jtable 单元格中实现「单元格内部分文字着色」的方法:一种是基于 html 标签的轻量级方案(推荐初学者使用),另一种是自定义 jcomponent 重写 paintcomponent 的高性能方案,并提供可直接运行的代码示例与适配建议。
在 Swing 的 JTable 中,标准的 TableCellRenderer(如 DefaultTableCellRenderer)仅支持对整个单元格文本统一设置前景色(setForeground()),无法直接为子字符串单独着色。但通过合理利用 Swing 渲染机制,我们完全可以实现「同一单元格内数字变蓝、其余文字保持黑色」这类精细化样式需求。以下是两种经过实践验证的主流方案:
✅ 方案一:HTML + JLabel(简洁可靠,推荐首选)
JLabel 原生支持 HTML 渲染(需以 开头),这使得我们无需重绘即可通过标签嵌套实现局部样式控制。核心思路是:将原始字符串按规则切分为「普通文本」和「需高亮部分」,再用 <span style="color:..."></span> 包裹目标片段。
以下是一个完整、健壮的 TableCellRenderer 实现:
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class MarkupRenderer implements TableCellRenderer {
private final DefaultTableCellRenderer delegate;
// 支持正负整数、小数(如 -12.34、+5、0.007)
private final Pattern numberPattern = Pattern.compile("[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?");
public MarkupRenderer() {
this.delegate = new DefaultTableCellRenderer();
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
String text = (value == null) ? "" : value.toString();
String htmlText = formatAsHtml(text);
return delegate.getTableCellRendererComponent(
table, htmlText, isSelected, hasFocus, row, column);
}
private String formatAsHtml(String s) {
StringBuilder sb = new StringBuilder("<html><body>");
Matcher m = numberPattern.matcher(s);
int lastEnd = 0;
while (m.find()) {
int start = m.start(), end = m.end();
// 添加前缀普通文本
if (start > lastEnd) {
sb.append(s, lastEnd, start);
}
// 高亮数字(蓝色)
sb.append("<span style="color:#0066cc;">")
.append(s, start, end)
.append("</span>");
lastEnd = end;
}
// 添加末尾剩余文本
if (lastEnd < s.length()) {
sb.append(s.substring(lastEnd));
}
sb.append("</body></html>");
return sb.toString();
}
}使用方式:
table.getColumnModel().getColumn(targetColumnIndex).setCellRenderer(new MarkupRenderer());
⚠️ 注意事项:
- HTML 渲染会略微增加字符串处理开销,但对常规表格(≤ 数千行)完全无感;
- 确保
JLabel的setOpaque(false)(默认即如此),避免背景遮盖;- 若单元格启用选中状态(
isSelected),HTML 不会影响选中高亮色——Swing 会自动叠加半透明蒙版,文字颜色仍清晰可辨。
✅ 方案二:自定义 JComponent + paintComponent(极致性能,适合高频刷新场景)
当表格行数极大(如 > 10 万)、且每帧都动态更新时,频繁构造 HTML 字符串可能成为瓶颈。此时可继承 JComponent,在 paintComponent(Graphics g) 中手动分段绘制文本:
class StyledTextRenderer extends JComponent implements TableCellRenderer {
private final FontMetrics fm;
private String text = "";
private final Pattern numberPattern = Pattern.compile("\d+");
public StyledTextRenderer() {
setOpaque(true); // 可根据需要设为 false 以支持透明背景
fm = getFontMetrics(getFont());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
int x = 5, y = fm.getAscent() + 5; // 简单内边距
int lastEnd = 0;
Matcher m = numberPattern.matcher(text);
while (m.find()) {
int start = m.start(), end = m.end();
// 绘制普通文本(黑色)
if (start > lastEnd) {
g2.setColor(Color.BLACK);
g2.drawString(text.substring(lastEnd, start), x, y);
x += fm.stringWidth(text.substring(lastEnd, start));
}
// 绘制数字(蓝色)
g2.setColor(Color.BLUE);
String num = text.substring(start, end);
g2.drawString(num, x, y);
x += fm.stringWidth(num);
lastEnd = end;
}
// 绘制结尾剩余文本
if (lastEnd < text.length()) {
g2.setColor(Color.BLACK);
g2.drawString(text.substring(lastEnd), x, y);
}
g2.dispose();
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
this.text = (value == null) ? "" : value.toString();
// 同步背景/字体/选中态(关键!)
setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
setFont(table.getFont());
return this;
}
}? 提示:此方案需自行管理字体度量、抗锯齿、背景填充及选中态同步,灵活性高但开发成本略大;适用于对性能极度敏感的专业桌面应用。
总结
- 日常开发首选 HTML 方案:代码简短、语义清晰、维护成本低,兼容所有 Swing L&F;
- 超大数据量或定制化渲染需求:采用自绘组件,可精确控制每个像素,支持渐变、图标混合等高级效果;
- 无论哪种方式,都应避免在
getTableCellRendererComponent中创建新对象(如new Color()、new Font()),优先复用已有实例以减少 GC 压力。
通过上述任一方法,你都能轻松实现类似 Text1test → “Text1test” 的精准着色效果,让表格信息表达更直观、专业。

















