Hi

I have a program that finds duplicate files and lists them in a Jtable. I have modified the default Table Renderer to change the colour of the cells but I want them to have more than two colours. Say Blue for the first set of say 5 files all of which are duplicates of each other, then the next three say green and all of which are duplicates again of each other but different to the first five. Naturally I do not know how many of the duplicates of each file exist nor do I know the values in either of the cells or rows.

I wrote a renderer but it changes all the rows to one colour defeating my purpose.

public class MyTableRenderer extends DefaultTableCellRenderer
{

    public MyTableRenderer()
    {

    }
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
    {
        Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        return this;
    }
    public void blue()
    {
        setBackground(Color.blue);
    }
    public void red()
    {
        setBackground(Color.red);
    }
}

in the class from which the rows are added I have a vector that reads 1 set of duplicates and enters a loop to start adding to the Jtable. Here I change I call the MytableRenderer.Blue() method. My logic as seen below:

if (colour == true)
                    {
                        renderer.blue();
                        colour = false;
                    }
                    else
                    {
                        renderer.red();
                        colour = true;
                    }
                  duplicates.addElement(r.elementAt(i));
                  for(int x=0;x<duplicates.size();x++)
                  {
                      addToTable(((File)duplicates.elementAt(x)));
                  }

                  duplicates.clear();[/ICODE]

Is this the right way or am I wrong?

Many thanks

Edited 3 Years Ago by Reverend Jim: Fixed formatting

First off, read the tutorial on using custom cell renders: http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#renderer
and here is another example: http://www.exampledepot.com/egs/javax.swing.table/CustRend.html?l=rel

The render will be called for each cell in the table that you have registered it for. Look at the parameters that are supplied when the render is requested:

getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex)

You have plenty of information available there to alter how it gets rendered based upon the particulars of that cell value or other information available in your class.

Here's an example of a renderer I used to color cells red or green when a gap exceeds minimum or maximum thresholds which can be set by the user in a couple of text fields on the panel:

class GapColRenderer extends DefaultTableCellRenderer{
    private final Color MIN_COLOR = Color.GREEN;
    private final Color MAX_COLOR = Color.RED;

    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) {

        Component comp = super.getTableCellRendererComponent(table,value,isSelected,hasFocus,rowIndex,vColIndex);

        if (((Double)value).doubleValue() > maxGapThreshold){
            if (isSelected){
                comp.setBackground(new Color((MAX_COLOR.getRGB() ^ comp.getBackground().getRGB())));
                comp.setForeground(new Color(Color.BLACK.getRGB() ^ comp.getForeground().getRGB()));
            } else {
                comp.setBackground(MAX_COLOR);
                comp.setForeground(Color.BLACK);
            }
        } else if (((Double)value).doubleValue() < minGapThreshold){
            if (isSelected){
                comp.setBackground(new Color((MIN_COLOR.getRGB() ^ comp.getBackground().getRGB())));
                comp.setForeground(new Color(Color.BLACK.getRGB() ^ comp.getForeground().getRGB()));
            } else {
                comp.setBackground(MIN_COLOR);
                comp.setForeground(Color.BLACK);
            }
        } else {
            if (isSelected){

            } else {
                comp.setBackground(Color.WHITE);
                comp.setForeground(Color.BLACK);
            }
        }
        return comp;
    }
}
Comments
Great info :)

All the examples seemingly require that you get a value from a cell which is checked in the

getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex)getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex)

function. This is obvious if you know the values that are to prompt the change in colour.
My situation is somewhat different. I have four columns, File Name, Last Modified, Size and absolute path. Now If I find sets of a duplicate file say 5, the names may be different and I do not know in advance which files are to be found making it more challenging to write a renderer before hand.

I have created a fifth column in which I place the colour of the cell e.g. say "blue" and then when the next round of duplicates comes I then place "red". I reduce the columnwith to 0 and make it as unadjustable so at runtime you cannot see it, well almost. It works perfectly but someone commented that it does not sound professional. Is that the case? if so any further help.

Many thanks

Well, somehow you determined that those entries were duplicates. It should be easy enough to retain that information in either the object that holds your file entry data or separate data structures like lists. All you really need is to be able to correlate that information with your table rows. That becomes rather trivial if you are using your own table model, but if you are using the DefaultTableModel then you might want to store the actual file entry object in a col, perhaps the Filename column, and just have the toString() method display the name you want to see. The rest of that data is still available but not cluttering up the table with hidden columns.

Indeed, I am using the defaultTableModel. I will see how I may write my own so as to meet my objective. While it works, I am still not happy with it.

Many thanks for your help.

This article has been dead for over six months. Start a new discussion instead.