anta40
anta40

Reputation: 6743

How to change JTable color cells at several different locations?

I have a JTable object which displays the content of an Excel table. Once another Excel table is loaded, the differences have to be displayed (so some cells will change its background color, blue for example). This is the structure of my table.

enter image description here

And this is my code:

 tblGSM.setDefaultRenderer(Object.class, new CustomTableRenderer(diffs));

CustomTableRenderer.java

public class CustomTableRenderer extends DefaultTableCellRenderer {

    private Vector<Diff> diffs;


public PersoTableRenderer(Vector<Diff> diffs){
    this.diffs = diffs;
}

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

   Component c = null;

    for (int x = 0; x < diffs.size(); x++){

        Diff d = diffs.elementAt(x);

        c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, 
                d.getRow(), d.getColumn());
        c.setBackground(Color.BLUE);
    }
    return c;
}}

Diff.java

/*
A class to store the difference of corresponding cells
*/

public class Diff {
    private int row, col;

    public Diff(int row, int col){
        this.row = row;
        this.col = col;
    }

    public Diff(){
        this(0,0);
    }

    public int getRow(){
        return row;
    }

    public int getColumn(){
        return col;
    }
}

My question is diffs is populated correctly, yet the cells colors which are should be changed are not. Turns out all cells in column 1, 2, ,3, and 7 are changed. What it the solution, then?

Upvotes: 0

Views: 421

Answers (1)

Jason C
Jason C

Reputation: 40315

From the documentation for DefaultTableCellRenderer (emphasis mine):

However JTable employs a unique mechanism for rendering its cells and therefore requires some slightly modified behavior from its cell renderer. The table class defines a single cell renderer and uses it as a as a rubber-stamp for rendering all cells in the table; it renders the first cell, changes the contents of that cell renderer, shifts the origin to the new location, re-draws it, and so on.

So as you can see, super.getTableCellRendererComponent() may return the same component for multiple cells, and thus your approach will not work.

Note that getTableCellRendererComponent is called once per cell as it is rendering, so in addition to the above caveat, your general approach of setting all renderer components in the table to blue when retrieving a single cell's component is not correct.

Instead you will want to only modify the background color of the component being requested, like (pseudo-code):

c = super.getTableCellRendererComponent(..., row, column)

// also don't forget to translate to model coords
model_row = table.convertRowIndexToModel(row)
model_column = table.convertColumnIndexToModel(column)

if diffs contains model_row,model_column:
    c.setBackground(blue)
else
    c.setBackground(table.getBackground()) // don't forget to reset

return c

Noting that you also have to reset the background color to its default if its not a "diff" cell, since as the docs state, the components are shared among multiple cells.

By the way, rather than storing the Vector<Diff> in your renderer, you really ought to be using a proper TableModel for this, and then querying the model for information. With a sanely implemented model this will also give you constant-time lookups of whether or not a cell should be blue, rather than having to search through the entire list of Diffs.

PS: Don't forget to translate your renderer/view coordinates to model coordinates when working with your Diffs, assuming they are in model coordinates. View coordinates may not agree with model coordinates if e.g. the table is sorted or the user has rearranged the columns. I've shown this in the above pseudo code.

Here is a complete example showing the use of a table model and per-cell custom backgrounds. You can sort the table and rearrange its columns.

Upvotes: 2

Related Questions