
本文介绍两种在 jtable 的 tablecellrenderer 中实现“同一单元格内混合文本颜色”的专业方案:一是基于 html 标签的轻量级实现(推荐初学者),二是自定义 jcomponent 重写 paintcomponent 的高性能方案,并提供可直接运行的 html 渲染器代码及关键注意事项。
本文介绍两种在 jtable 的 tablecellrenderer 中实现“同一单元格内混合文本颜色”的专业方案:一是基于 html 标签的轻量级实现(推荐初学者),二是自定义 jcomponent 重写 paintcomponent 的高性能方案,并提供可直接运行的 html 渲染器代码及关键注意事项。
在 Swing 的 JTable 中,标准 TableCellRenderer(如 DefaultTableCellRenderer)仅支持为整个单元格文本统一设置前景色(setForeground()),无法直接高亮其中特定字符。但通过合理利用 Swing 的渲染机制,完全可以实现类似「Text1test」这样的细粒度着色效果。以下提供两种经过实践验证的方案:
✅ 方案一:HTML 渲染器(简洁可靠,推荐首选)
Swing 的 JLabel 原生支持有限 HTML 4.0 渲染(通过 标签启用),因此可将文本动态转换为含内联样式的 HTML 字符串。例如将 "Text1test" 转为:
<html><body>Text<span style="color:#0000ff;">1</span>test</body></html>
DefaultTableCellRenderer 内部即基于 JLabel,因此只需预处理字符串即可生效。
以下是完整、健壮的 MarkupRenderer 实现(已适配负数与小数):
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MarkupRenderer implements TableCellRenderer {
private final DefaultTableCellRenderer delegate;
// 支持整数、负数、小数(如 -3.14, 0.5, +7)
private final Pattern numberPattern = Pattern.compile("[-+]?\d*\.?\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 = toHtmlWithColoredNumbers(text);
return delegate.getTableCellRendererComponent(
table, htmlText, isSelected, hasFocus, row, column);
}
private String toHtmlWithColoredNumbers(String s) {
if (s == null || s.isEmpty()) return "<html><body></body></html>";
StringBuilder sb = new StringBuilder("<html><body>");
Matcher m = numberPattern.matcher(s);
int lastEnd = 0;
while (m.find()) {
int start = m.start();
int end = m.end();
// 添加非数字前缀
if (start > lastEnd) {
sb.append(s, lastEnd, start);
}
// 高亮数字(蓝色)
sb.append("<span style="color:#0000ff;">")
.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 渲染会略微增加 CPU 开销(字符串拼接 + HTML 解析),但对常规表格(≤1000 行)完全无感;
- 不支持富文本字体/大小混排(仅颜色、粗体等基础样式);
- 确保
value为String类型,若为其他对象请在format()中调用toString()并做空值防护;- 若需深色主题兼容,请改用
#4285f4等更高对比度蓝色。
✅ 方案二:自定义 JComponent + paintComponent()(高性能进阶)
当表格行数极多(如上万行)、且需极致渲染性能时,可继承 JComponent,在 paintComponent(Graphics g) 中手动分段绘制文本:
public class CustomTextRenderer extends JComponent implements TableCellRenderer {
private final FontMetrics fm;
private String text = "";
private final Color defaultColor = Color.BLACK;
private final Color numberColor = new Color(0, 0, 255);
public CustomTextRenderer() {
setOpaque(true);
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 = 4; // 左侧内边距
int y = fm.getAscent() + 2;
Matcher m = numberPattern.matcher(text);
int lastEnd = 0;
while (m.find()) {
int start = m.start(), end = m.end();
// 绘制非数字部分(黑色)
if (start > lastEnd) {
g2.setColor(defaultColor);
g2.drawString(text.substring(lastEnd, start), x, y);
x += fm.stringWidth(text.substring(lastEnd, start));
}
// 绘制数字部分(蓝色)
g2.setColor(numberColor);
String numStr = text.substring(start, end);
g2.drawString(numStr, x, y);
x += fm.stringWidth(numStr);
lastEnd = end;
}
// 绘制结尾剩余文本
if (lastEnd < text.length()) {
g2.setColor(defaultColor);
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();
if (isSelected) {
setBackground(table.getSelectionBackground());
setForeground(table.getSelectionForeground());
} else {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
return this;
}
}该方案避免了 HTML 解析开销,适合高频滚动场景,但需自行处理选中态背景、焦点边框、字体度量等细节,开发成本较高。
总结
- 日常开发首选 HTML 方案:代码简洁、维护性高、兼容性好,足以覆盖 95% 的需求;
- 超大表格或定制化要求高时选用自绘方案:需权衡开发复杂度与性能收益;
- 无论哪种方案,都应将正则逻辑封装为可配置项(如支持自定义高亮规则、颜色、匹配模式),以提升复用性。
通过上述任一方式,你都能优雅地实现 JTable 单元格内「数字蓝色、其余黑色」等精细化文本渲染效果。

















