Java Tips Weblog

  • Blog Stats

    • 1,281,408 hits
  • Categories

  • Archives

Table Row Rendering

Posted by Rob Camick on January 24, 2010

There are times when you might want to do some custom rendering for an entire row of a table. Based on answers I see in the forums, for most people the first thought is to create a custom renderer. This can be a simple solution in some cases, but are there other alternatives to consider as well?

A renderer is used by a JTable to render a class of data for a given column. So when all the data in the table is of the same class, String for example, then the easiest solution is probably to create a custom String renderer containing your custom row rendering logic.

However, what happens when your table contains multiple classes of data, maybe String, Date, Integer and Boolean? Would you create 4 custom renderers or is there a better way?

In this situation it is possible to write the custom rendering code only once and have it applied to all renderers. The trick is to override the prepareRenderer(…) method of JTable. This method is invoked every time a cell is rendered so it is the perfect place to add row level rendering logic that can be applied to all renderers.

The basic structure for overriding this method would be as follows:

JTable table = new JTable(...)
{
    public Component prepareRenderer(
        TableCellRenderer renderer, int row, int column)
    {
        Component c = super.prepareRenderer(renderer, row, column);

        //  add custom rendering here

        return c;
    }
};

 You can use this technique to alternate the background color of each row:

… add a row level Border:

… change the background color based on data in the row:

Although this tip was suggested to be used for row rendering. It can be considered any time you want to add common logic to multiple different renderers.

Get The Code

TableRowRenderingTip.java

Related Reading

Java Tutorials: Concepts – Editor and Renderers

About these ads

22 Responses to “Table Row Rendering”

  1. tbee said

    I’m using this beauty of a hook-in method for all kinds of goodies, like for example:
    – highlight a cell when the value has an error or warning (by wrapping it in a JPanel with a red / orange border)
    – automatically adjust the height of a row if the renderer requires additional room

    This saves the trouble of implementing logic in each and every cell render implementation.

  2. Kleopatra said

    Rob,

    exactly what SwingX does – formalized into “Highlighter” which are pluggable by table (and list, tree) or by column :-)

    The one problem with this approach is that the renderer must play strictly by the rules, that is reset all visual properties in each call to getXXCellRenderingComponent. Most default renderers are misbehaving in one way or another, particularly unfortunate is DefaultTableCellRenderer which doesn’t do so with its colors.

    @Tom, careful: size changing in the prepare can lead to changing the state of the table during the a paint cycle which is a Bad-Thing

    Cheers
    Jeanette

    • Rob Camick said

      As usual, good point about resetting the renderer state. At least my examples take that into account, at least I have not noticed any problems.

      Once I get back from vacation I will update the posting to specifically mention this potential problem.

    • Denis Lemberger said

      Setting the background color using this technique doesn’t work when the renderer is a subclasses of DefaultTreeCellRenderer. It’s background simply remains white.

      Actually setting the background color of a DefaultTreeCellRenderer doesn’t work at all (not even when overriding getTreeCellRendererComponent())!

      Any hints?

      Many thanx in advance
      :-Denis

      • Rob Camick said

        Sorry, I”m not familiar with the details of the Tree renderer. You can try looking at the source code for the default Tree and Table renderers to see why they work differently.

  3. tbee said

    That is exactly why I used the JPanel for my error / warning border; nicely under my own control. Even tried doing the alternating background using that, but the renderer has to be transparent then, and that usually is not the case.

    @Jeanette: no problems so far, but as soon as I run into one I’ll “invokeLater” the call

    I just saw that I use the same hook to make the component look disabled if the cell is not editable.

  4. SongLi said

    Thanks for this solution. However, when I added row sorter, the table color will not change after row sorting. Any suggestion about this problem?

    • Rob Camick said

      When using a table you need to understand the difference between working with the “model” or the “view” when accessing the data. The example code for the “Data” tab has been updated to include sorting on the table and all indexes are converted to model values in the prepare renderer code.

  5. Bob said

    Sorry about this silly question, but following your example, my prepareRederer isn’t being called, so my rows aren’t rendered. Could you help me? What am I doing wrong?

  6. sam said

    Thanks so much for this tutorial. I’m a C++ coder moving to Java and this really helped me a lot.

    Have an eBeer on me!

    Sam

  7. a said

    Thank you so much dude! I kept having the problem that my jtable only set the back ground of two rows using a custom default renderer – both of them strings and couldn’t figure out what that was! In addition if I select a row then the background and font color is also white – so I can’t see the text!!!!! This has solved both problems!!!

  8. I made of this today :) And found the difference between custom renderer and prepareRenderer() :) Thanks again Rob Camick…

  9. rishu said

    If I have a row sorter enable for each column , then this does not help. I mean if u sort rows by double clicking on a column header, the color changes are sticky to cells and do not get reflected on the correct data.

    • Rob Camick said

      If you are getting data from the model then you will need to use:

      int modelRow = convertRowIndexToModel( row );
      

      and then access the model data using the modelRow variable.

  10. Anonymous said

    Hi,

    I’ve used your tip for painting odd rows, but it happens that the selection color is not shown in those rows. Any idea why would it be?

    Thanks

  11. Jacky said

    Hi there,
    It’s Jack here. I wonder why when I plug your code into mine
    I got different results

    http://www.coderanch.com/t/621513/GUI/java/JTable-Rendering-Stangeness#2840262

    Let me know
    Thanks
    Jack

    • Rob Camick said

      Seriously? Every time I answer one of your questions in that forum you never bother to reply with a simple thank you. It is not just me, you rarely reply to anybody who takes the time to help you. Also, how many times have you been asked to post a SSCCE with your questions. Once again you did NOT post a SSCCE. Now you expect me to give you personal attention. I’m sorry, until you learn to use the forums properly and learn to respect the help you are given you are on your own.

  12. Robert Schmidt said

    Hi Rob!

    After two days searching the web, I found your code. You saved my day! Everything else I tried didn’t work using NetBeans, this does.
    Great work.

    Thanks

  13. Chakib said

    Thanks a lot ;)
    it’s a good job

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 97 other followers

%d bloggers like this: