I've got a JTable called chances_T full of doubles ranging from 0 to 100.
I'm trying to set the background color of each cell based on the cell's value.
So I built a custom cell renderer:

class CustomRenderer extends 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);
            double chance = Double.parseDouble(String.valueOf(value));
            if (chance > 80) {
                c.setBackground(Color.green);
                console_TA.append("Worked!\n");
            } else if (chance >= 50 && chance < 80) {
                c.setBackground(Color.yellow);
            } else if (chance >= 25 && chance < 50) {
                c.setBackground(Color.orange);
            } else if (chance >= 10 && chance < 25) {
                c.setBackground(Color.red);
            } else if (chance > 10) {
                c.setBackground(Color.gray);
            }            
            return c;
        }
    }

I initialized this renderer after I seeded the table with values (the seeding method works correctly):

CustomRenderer CR = new CustomRenderer();
for (int i = 1; i < 5; i++) {
    for (int j = 0; j < 9; j++){
        CR.getTableCellRendererComponent(this.chances_T, data[i][j], false, true, i, j);
    }
}     

It goes through the whole thing, it shows the values, but the cells' background colors remain unchanged. It even appends "Worked!" into the JTextArea called console_TA.
I'll continue experimenting on this!

Edited 2 Years Ago by Pobunjenik

I suppose you did remember to call setDefaultRenderer or setCellRenderer (for the relevant columns)?

And did you setOpaque(true)? because the default renderer is a JLabel, which is opaque(false) by default, so it never shows its background colour.

Edited 2 Years Ago by JamesCherrill

I love you so much. <3

Solution:

class CustomRenderer extends 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);
            TableColumn tacol = table.getColumnModel().getColumn(column); // this was missing
            tacol.setCellRenderer(this); // this was missing
            double chance = Double.parseDouble(String.valueOf(value));
            if (chance > 80) {
                c.setBackground(Color.green);
                console_TA.append("Worked!\n");
            } else if (chance >= 50 && chance < 80) {
                c.setBackground(Color.yellow);
            } else if (chance >= 25 && chance < 50) {
                c.setBackground(Color.orange);
            } else if (chance >= 10 && chance < 25) {
                c.setBackground(Color.red);
            } else if (chance > 10) {
                c.setBackground(Color.gray);
            }            
            return c;
        }
    }

That presumably works because you called the renderer yourself in order to initialise it (normally there's no reason to do that).
If your renderer is for all the cells in the table it's easier to just to call setDefaultRenderer for your JTable once, as in
myTable.setDefaultRenderer(new CustomRenderer());

ps I'm very happily married, so your love must remain unrequited. Sorry. :)

Edited 2 Years Ago by JamesCherrill

Looks like I've had luck there, because the code doesn't render all cells (the first column stays unedited).

In short: it works. :)

PS
Damn.

  1. never to set column coordinates inside XxxTableCellRenderer
  • TableColumn tacol = table.getColumnModel().getColumn(column); // this was missing

nor columns target,

  • tacol.setCellRenderer(this); // this was missing

  • both above code lines is way directly to the troubles

  1. this renderer can works for whole JTables view visible on the screen, more info about is in official Oracle tutorial, How to use Tables, these desciptions are very clear
  • row, column from Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); returns coordinates in the JTables view, test for column or row,

  • everything works until JTables view isn't sorted, filtered, column is removed or reordered, then is required to convert index from views coordinates to model

  • override getColumnClass in XxxTableModel, then double chance = Double.parseDouble(String.valueOf(value)); is useless, set there Double.Class, put Double value to XxxTableModel

Edited 2 Years Ago by mKorbel

@JamesCherrill

ps I'm very happily married, so your love must remain unrequited. Sorry. :)

much luck .........., stay as you are, then nothing will be changed

Could you please go above "don't do this" and explain why?

The cells are rendered correctly, I've tried it many times.

  • initial 1st code is correct,

  • renderer is added to JTable

  • reduce loop by test column (e.g if(column == 4)) coordinates (arrays in java start with zero value)

  • if column index passed then test for value from row

  • renderer by defaul loop inside whole JTables view, there isn't required additional loop only to test by if - else if - else

  • use else block only for reseting renderer setWhatever(table.getWhatever)

This question has already been answered. Start a new discussion instead.