You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在JTable中设置满足特定条件的文本颜色?低于40分文本变红却全部变红的问题排查

问题分析与解决方案

嗨,这问题我一眼就看出来啦!你之所以会出现所有文本都变红的情况,核心原因是你在循环里修改的是整个JTable的前景色,而不是单个单元格/行的颜色

错误原因拆解

你写的这段循环代码:

for (int i = 0; i < tb1.getRowCount(); i++) {
    Object x = tb1.getValueAt(i, 1);
    String y = x.toString();
    double z = Double.parseDouble(y);
    if (z < 40) {
        tb1.setForeground(Color.RED);
    } else {
        tb1.setForeground(new Color(38, 120, 81));
    }
}

每次循环都会给整个tb1(也就是整个表格)设置前景色,循环最后一次执行的是第二行(Amy的30分),此时触发tb1.setForeground(Color.RED),所以整个表格的文字都变成红色了——前面的设置全被最后一次覆盖掉了。

正确的解决方法:使用TableCellRenderer

要实现单个单元格/行的颜色自定义,我们需要使用TableCellRenderer(表格单元格渲染器),它能让我们对每个单元格的显示样式单独控制。

下面是修改后的完整代码,我替换了原来的循环部分,改用自定义渲染器:

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class testing{
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                mark();
            }
        });
    }
    public static void mark() {
        String[] columns = new String[] {"Name", "Marks(%)"};
        Object[][] data= new Object[][] {
            {"Aby", "100"},
            {"Amy", "30"}
        };
        JFrame frame = new JFrame("Student Marks List");
        frame.setVisible(true);
        frame.setSize(600, 500);
        frame.setLayout(new BorderLayout());
        Panel details = new Panel(null);
        details.setBounds(0,50, 1000, 125);
        Panel contents = new Panel(null);
        contents.setBounds(0,50, 1000, 600);
        frame.add(details, BorderLayout.NORTH);
        frame.add(contents, BorderLayout.CENTER);
        JTable tb1;
        tb1 = new JTable(data, columns);
        JScrollPane sp = new JScrollPane(tb1);
        tb1.getTableHeader().setOpaque(false);
        tb1.getTableHeader().setFont(new Font("Barlow Condensed ExtraBold", Font.BOLD, 20));
        tb1.getTableHeader().setPreferredSize(new Dimension(100, 30));
        tb1.setFont(new Font("Barlow Condensed", Font.BOLD, 20));
        tb1.setRowHeight(30);

        // 自定义单元格渲染器,替代原来的循环
        DefaultTableCellRenderer markRenderer = new DefaultTableCellRenderer(){
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, 
                                                           boolean isSelected, boolean hasFocus, 
                                                           int row, int column) {
                // 先调用父类方法获取默认渲染组件
                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                // 只针对Marks列(索引1)进行颜色设置
                if(column == 1){
                    try{
                        double mark = Double.parseDouble(value.toString());
                        if(mark < 40){
                            c.setForeground(Color.RED);
                        }else{
                            c.setForeground(new Color(38, 120, 81));
                        }
                    }catch(NumberFormatException e){
                        // 如果值不是数字,用默认颜色
                        c.setForeground(table.getForeground());
                    }
                }else{
                    // 其他列用默认颜色
                    c.setForeground(table.getForeground());
                }
                // 设置居中对齐(把你原来的centerRenderer功能整合进来了)
                setHorizontalAlignment(JLabel.CENTER);
                return c;
            }
        };
        // 把渲染器应用到Marks列
        tb1.getColumnModel().getColumn(1).setCellRenderer(markRenderer);
        // 其他列也设置居中对齐
        DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
        centerRenderer.setHorizontalAlignment(JLabel.CENTER);
        tb1.getColumnModel().getColumn(0).setCellRenderer(centerRenderer);

        tb1.setBounds(25,10,200,375);
        sp.setBounds(25,10,200,375);
        contents.add(sp);
    }
}

代码关键点说明

  • 我们继承DefaultTableCellRenderer并重写getTableCellRendererComponent方法,这个方法会为每个单元格返回渲染组件,所以能单独控制每个单元格的样式。
  • 只针对第二列(column == 1)进行分数判断,其他列保持默认样式。
  • 加入了异常处理,防止单元格值不是数字时出错。
  • 把你原来的居中对齐需求也整合到了渲染器里,让代码更简洁。

这样修改后,只有低于40分的单元格文字会变成红色,其他分数和姓名列都会显示你设置的绿色啦~

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

火山引擎 最新活动