tags:

views:

481

answers:

2

I have a Jtable and I want to highlight a row by adding a border to the row. I have extended a DefaultTableCellRenderer and I figure the work needs to be done in the getTableCellRendererComponent method.

I'm guessing that since there doesn't seem to be a concept of a row that I need to create a custom border for the individual cells in the row. Something like a left side, top, and bottom for the first cell, a top and bottom for all the inner cells, and a top, bottom, and right side for the last cell in the row. I'm having problems finding out how to go about actually executing the thought process. I'm not sure how to use the setBorder() method or if that's even the direction I need to take.

+1  A: 

You have the correct idea in mind, you will need to set the border on the label in the cellrenderer depending on where it is in the table(i.e. edge, center etc).

Take a look at matteborder. You can specify which areas to draw a border along w/ width and color.

broschb
+1, but I'm outta votes :)
Carl Smotricz
Thanks, that pointed me in the right direction. I'll edit my question with a more complete answer for future reference.
Ryan Elkins
+1  A: 

I would not create a custom renderer for this. Yes it will work if all your data is of the same type. But what happens when you start to mix Strings, with Dates and Integers and Booleans which all use different renderers? Then you would need to create 4 custom renderers.

The better approach is to override the prepareRenderer(...) method JTable so you can add the code in one place. Here is an example to get you started. In reality you would want to use a CompoundBorder that contains a MatteBorder for the top/bottom and and EmptyBorder for the left/right and you would create a single instance of the Border.

import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
import javax.swing.border.*;

public class TablePrepareRenderer extends JFrame
{
    JTable table;

    public TablePrepareRenderer()
    {
     Object[] columnNames = {"Type", "Company", "Shares", "Price", "Boolean"};
     Object[][] data =
     {
      {"Buy", "IBM", new Double(1000), new Double(80.5), Boolean.TRUE},
      {"Sell", "MicroSoft", new Double(2000), new Double(6.25), Boolean.TRUE},
      {"RSell", "Apple", new Double(3000), new Double(7.35), Boolean.TRUE},
      {"Buy", "Nortel", new Double(4000), new Double(20), Boolean.TRUE}
     };

     DefaultTableModel model = new DefaultTableModel(data, columnNames);
     table = new JTable( model )
     {
      //  Returning the Class of each column will allow different
      //  renderers to be used based on Class

      public Class getColumnClass(int column)
      {
       return getValueAt(0, column).getClass();
      }

      public Component prepareRenderer(
       TableCellRenderer renderer, int row, int column)
      {
       Component c = super.prepareRenderer(renderer, row, column);
       JComponent jc = (JComponent)c;

       //  Color row based on a cell value
       //  Alternate row color

       if (!isRowSelected(row))
        c.setBackground(row % 2 == 0 ? getBackground() : Color.LIGHT_GRAY);
       else
        jc.setBorder(new MatteBorder(1, 0, 1, 0, Color.RED) );


       //  Use bold font on selected row

       return c;
      }
     };

     table.setPreferredScrollableViewportSize(table.getPreferredSize());
     table.changeSelection(0, 0, false, false);
     JScrollPane scrollPane = new JScrollPane( table );
     getContentPane().add( scrollPane );
    }

    public static void main(String[] args)
    {
     TablePrepareRenderer frame = new TablePrepareRenderer();
     frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
     frame.pack();
     frame.setLocationRelativeTo( null );
     frame.setVisible(true);
    }
}
camickr
I already had a custom cellrenderer from some other requirements, but the different data types didn't cause any problems.
Ryan Elkins
It doesn't matter. This approach doesn't care what cell renderer you are using. that is the key to the solution. It will work the the default renderers or your custom renderer.
camickr
By the way if you have a renderer that renders Date, Integers, String and Booleans in a single renderer, that is a terrible design.
camickr