简体   繁体   中英

Change the font color in a specific cell of a JTable?

Before starting, I've viewed a handful of solutions as well as documentation. I can't seem to figure out why my code isn't working the way I believe it should work. I've extended DefaultTableCellRenderer but I don't believe it is being applied - that or I messed things up somewhere.

Here are the threads / websites I've looked into before posting this question:

I realize the first link uses HTML to change the font color, but I would think the way I went about it should produce the same result.

To make it easier on those who want to help me figure out the issues, I've created an SSCCE.

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;


public class TableTest {

    private static final int IMPORTANT_COLUMN = 2;

    public static void createAndShowGUI() {
        Object[][] data = new Object[2][4];
        //create sample data
        String[] realRowData = { "1", "One", "1.0.2", "compile" };
        String[] fakeRowData = { "2", "Two", "1.3.2-FAKE", "compile" };
        //populate sample data
        for(int i = 0; i < realRowData.length; i++) {
            data[0][i] = realRowData[i];
            data[1][i] = fakeRowData[i];
        }

        //set up tableModel
        JTable table = new JTable();
        table.setModel(new DefaultTableModel(data, 
                new String[] { "ID #", "Group #", "version", "Action" }) 

            {
                Class[] types = new Class[] {
                    Integer.class, String.class, String.class, String.class
                };

                boolean[] editable = new boolean[] {
                    false, false, true, false  
                };

                @Override
                public Class getColumnClass(int columnIndex) {
                    return types[columnIndex];
                }

                @Override
                public boolean isCellEditable(int rowIndex, int columnIndex) {
                    return editable[columnIndex];
                }
            });

        //set custom renderer on table
        table.setDefaultRenderer(String.class, new CustomTableRenderer());

        //create frame to place table
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setMinimumSize(new Dimension(400, 400));
        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setViewportView(table);
        f.add(scrollPane);
        f.pack();
        f.setVisible(true);

    }

    //MAIN
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                createAndShowGUI();
            }
        });
    }

    //Custom DefaultTableCellRenderer
    public static class CustomTableRenderer extends DefaultTableCellRenderer {
        public Component getTableCellRenderer(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column)
        {
            Component c = super.getTableCellRendererComponent(table, value, isSelected,
                    hasFocus, row, column);

            String versionVal = table.getValueAt(row, IMPORTANT_COLUMN).toString();

            if(versionVal.contains("FAKE")) {
                //set to red bold font
                c.setForeground(Color.RED);
                c.setFont(new Font("Dialog", Font.BOLD, 12));
            } else {
                //stay at default
                c.setForeground(Color.BLACK);
                c.setFont(new Font("Dialog", Font.PLAIN, 12));
            }
            return c;
        }

    }
}

My goal is to highlight any value in the version column that contains the word FAKE in a red bold text.

I've extended DefaultTableCellRenderer but I don't believe it is being applied

Some simple debugging tips:

  1. Add a simple System.out.println(...) to the method you think should be invoked
  2. When overriding a method, make sure you use the @Override annotation (you used it in the TableModel class, but not your renderer class).

Your problem is a typing mistake because you are not overriding the proper method:

    @Override
    // public Component getTableCellRenderer(...) // this is wrong
    public Component getTableCellRendererComponent(...)

The override annotation will display a compile message. Try it before changing the code.

Also, your first column is NOT an Integer class. Just because it contains String representations of an Integer does not make it an Integer. You need to add an Integer object to the model.

Replace your custom table cell rendere with the below.

Explanations are in comments. Basically, you should override getTableCellRendererComponent then check for correct column (there may be other methods instead of checking header value), then set cell depending on color.

Do not forget last else block to set color to default if it is not the column you want.

//Custom DefaultTableCellRenderer
public static class CustomTableRenderer extends DefaultTableCellRenderer {

    // You should override getTableCellRendererComponent
    @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);

        // Check the column name, if it is "version"
        if (table.getColumnName(column).compareToIgnoreCase("version") == 0) {
            // You know version column includes string
            String versionVal = (String) value;

            if (versionVal.contains("FAKE")) {
                //set to red bold font
                c.setForeground(Color.RED);
                c.setFont(new Font("Dialog", Font.BOLD, 12));
            } else {
                //stay at default
                c.setForeground(Color.BLACK);
                c.setFont(new Font("Dialog", Font.PLAIN, 12));
            }
        } else {
            // Here you should also stay at default
            //stay at default
            c.setForeground(Color.BLACK);
            c.setFont(new Font("Dialog", Font.PLAIN, 12));
        }
        return c;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM