Uitable cell colors

A client recently asked me to develop an application that will help discover technical indicators for trading on the stock market. The application was very data-intensive and the analysis naturally required visual presentations of number-crunching results in a readable manner. One of the requirements was to present numeric results in a data table, so we naturally use uitable for this.

Today I will show how using some not-so-complex Java we can transform the standard Matlab uitable into something much more useful.

First pass – basic data table

We start by displaying the data in a simple uitable. The essence of the relevant code snippet was something like this:

headers = {'Periods', ...
           '<html><center>Any period<br />returns</center></html>', ...
           '<html><center>Avg return<br />signal</center></html>', ...
           '<html><center>Avg<br />gain</center></html>', ...
           '<html><center>Avg<br />draw</center></html>', ...
           '<html><center>Gain/draw<br />ratio</center></html>', ...
           '<html><center>Max<br />gain</center></html>', ...
           '<html><center>Max<br />draw</center></html>', ...
           '<html><center>Random<br />% pos</center></html>', ...
           '<html><center>Signal<br />% pos</center></html>', ...
           'Payout', '% p-value'};
hTable = uitable('Data',data, 'ColumnEditable',false, ...
           'ColumnName',headers, 'RowName',[], ...
           'ColumnFormat',['numeric',repmat({'bank'},1,11)], ...
           'ColumnWidth','auto', ...
           'Units','norm', 'Position',[0,.75,1,.25]);

Plain data table - so boooooring...

Plain data table - so boooooring...

We can see from this simple example how I have used HTML to format the header labels into two rows, to enable compact columns. I have already described using HTML formatting in Matlab controls in several articles on this website. I have not done this here, but you can easily use HTML formatting for other effect such as superscript (<sup>), subscript (<sub>), bold (<b>), italic (<i>), font sizes and colors (<font>) and other standard HTML effects.

Even with the multi-line headers, the default column width appears to be too wide. This is apparently an internal Matlab bug, not taking HTML into consideration. This causes only part of the information to be displayed on screen, and requires the user to either scroll right and left, or to manually resize the columns.

Second pass – auto-resizing that actually works…

To solve the auto-resizing issue, we resort to a bit of Java magic powder. We start by using the findjobj utility to get the table’s underlying Java reference handle. This is the containing scrollpane, and we are interested in the actual data table inside. We then use the setAutoResizeMode, as described in the official Java documentation.

jScroll = findjobj(hTable);
jTable = jScroll.getViewport.getView;
jTable.setAutoResizeMode(jTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);

Auto-resized columns that actually work

Auto-resized columns that actually work

Third pass – adding colors

There are still quite a few other customizations needed here: enable sorting; remove the border outline; set a white background; set row (rather than cell) selection and several other fixes that may seem trivial by themselves but together giver a much more stylish look to the table’s look and feel. I’ll skip these for now (interested readers can read all about them, and more, in my detailed uitable customization report).

One of the more important customizations is to add colors depending on the data. In my client’s case, there were three requirements:

  • data that could be positive or negative should be colored in green or red foreground color respectively
  • large payouts (abs > 2) should be colored in blue
  • data rows that have statistical significance (%p-value < 5) should have a yellow background highlight

While we could easily use HTML or CSS formatting to do this, this would be bad for performance in a large data table, may cause some issues when editing table cells or sorting columns. I chose to use the alternative method of cell renderers.

ColoredFieldCellRenderer is a simple table cell renderer that enables setting cell-specific foreground/background colors and tooltip messages (it also has a few other goodies like smart text alignment etc.). This requires some Java knowledge to program, but in this case you can simply download the ColoredFieldCellRenderer.zip file and use it, even if you don’t know Java. The source code is included in the zip file, for anyone who is interested.

After using javaaddpath to add the zip file to the dynamic Java classpath (you can add it to the static classpath.txt file instead), the contained Java class file is available for use in Matlab. We configure it according to our data and then assign it to all our table’s columns.

Java savvy readers might complain that the data-processing should perhaps be done in the renderer class rather than in Matlab. I have kept it in Matlab because this would enable very easy modification of the highlighting algorithm, without any need to modify the generic Java renderer class.

Unfortunately, in the new uitable design (the version available since R2008a), JIDE and Matlab have apparently broken the standard MVC approach by using a table model that not only controls the data but also sets the table’s appearance (row-striping background colors, for example), and disregards column cell-renderers. In order for our custom cell renderer to have any effect, we must therefore replace Matlab’s standard DefaultUIStyleTableModel with a simple DefaultTableModel. This in itself is not enough – we also need to ensure that the uitable has an empty ColumnFormat property, because if it is non-empty then it overrides our cell-renderer.

In the following code, note that Java row and column indices start at 0, not at 1 like in Matlab. We need to be careful about indices when programming java in Matlab.

The rest of the code should be pretty much self explanatory (again – more details can be found in the above-mentioned report):

% Initialize our custom cell renderer class object
javaaddpath('ColoredFieldCellRenderer.zip');
cr = ColoredFieldCellRenderer(java.awt.Color.white);
cr.setDisabled(true);  % to bg-color the entire column
 
% Set specific cell colors (background and/or foreground)
for rowIdx = 1 : size(data,1)
 
  % Red/greed foreground color for the numeric data
  for colIdx = 2 : 8
    if data(rowIdx,colIdx) < 0
      cr.setCellFgColor(rowIdx-1,colIdx-1,java.awt.Color(1,0,0));    % red
    elseif data(rowIdx,colIdx) > 0
      cr.setCellFgColor(rowIdx-1,colIdx-1,java.awt.Color(0,0.5,0));  % green
    end
  end
 
  % Yellow background for significant rows based on p-value
  if data(rowIdx,12) < = 5 && data(rowIdx,11)~=0
    for colIdx = 1 : length(headers)
      cr.setCellBgColor(rowIdx-1,colIdx-1,java.awt.Color(1,1,0));    % yellow
    end
  end
 
  % Bold blue foreground for significant payouts
  if abs(data(rowIdx,11)) >= 2
    cr.setCellFgColor(rowIdx-1,10,java.awt.Color(0,0,1));    % blue
 
    % Note: the following could easily be done in the renderer, just like the colors
    boldPayoutStr = ['<html><b>' num2str(data(rowIdx,11),'%.2f') '</b></html>'];
    %jTable.setValueAt(boldPayoutStr,rowIdx-1,10);  % this is no good: overridden when table model is replaced below...
    dataCells{rowIdx,11} = boldPayoutStr;
  end
end
 
% Replace Matlab's table model with something more renderer-friendly...
jTable.setModel(javax.swing.table.DefaultTableModel(dataCells,headers));
set(hTable,'ColumnFormat',[]);
 
% Finally assign the renderer object to all the table columns
for colIdx = 1 : length(headers)
  jTable.getColumnModel.getColumn(colIdx-1).setCellRenderer(cr);
end

Finally something lively!

Finally something lively!

This may not take a beauty contest prize, but you must admit that it now looks more useful than the original table at the top of this article.

Related posts:

  1. Uitab colors, icons and images Matlab's semi-documented tab panels can be customized using some undocumented hacks...
  2. Uitable customization report In last week’s report about uitable sorting, I offered a report that I have written which covers uitable customization in detail. Several people have asked for more details about the contents of this report. This is a reasonable request, and...
  3. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
  4. Changing Matlab’s Command Window colors Matlab's Command Window foreground and background colors can be modified programmatically, using some of Matlab's undocumented internal Java classes. Here's how....
  5. Multi-line uitable column headers Matlab uitables can present long column headers in multiple lines, for improved readability. ...
  6. Changing Matlab’s Command Window colors – part 2 The Matlab Command Window enables a limited degree of inline color customization - this post describes how to use it...

Categories: GUI, Java, Medium risk of breaking in future versions, UI controls

Tags: , , , , ,

Bookmark and Share Print Print

41 Responses to Uitable cell colors

  1. Younes says:

    Hello,
    Thank you for the contribution. I succeeded to replicate the example above but I have a problem. Only the data in blue appears because variable dataCells is not empty there but the other data doesn’t appear. I initialized dataCells = num2cell(data), then, the data appear as desired. But the problem is that I have no more access to the callback funtions to edit the table for example or select a cell.
    Do you have an explanation (and a solution :) ) to that. I use Matlab7.11.0(R2010b).
    Best regards,
    Younes

    • Yair Altman says:

      @Younes, this is because we replaced the table model, to which the callbacks were connected. If you would like my help in attaching callbacks to the new table model, then please email me (you can use the link at the top right of every webpage on this website).

  2. Lech says:

    Hi Yair,

    First of all thank you for running that blog and helping to discover new ways of MATLAB ;)
    My problem is as follows. I’d like to disable one of the rows of the uitable from being able to be edited. I can do it with columns with a build in MATLAB method ColumnEditable, but apparently nobody thought of the case when someone would like to do that with rows. I created my own DefaultTableModel and attached it to the table. The disabling works, but in the process I lose all my callbacks. Is there any way to attach the standard CellEditCallback to the new table model?

    All the best,
    Lech

    • Yair Altman says:

      @Lech – Swing’s JTable, on which uitable is ultimately based, uses a data model that is column-based, not row-based. Lots of different inconsistencies arise out of this, row-editability is just one of them.

      You cannot use Matlab’s standard callbacks after you modified the table model, but you can use callbacks at the Java level. If you want my help in this, please email me (you can use the link at the top right of every webpage on this website).

  3. Jayveer says:

    hello

    doesn’t the use of javaaddpath make this unusable for matlab compiled standalone applications?

    is there a way around it?

  4. Carly says:

    Hello,

    I love your blog and find it very helpful! I used this code in R2011b and it worked beautifully. However, now that I upgraded to R2012a when I use the same code the font turns gray and when I change the background color I get a kind of 3-D effect with the font. Any idea what is causing this? Thank you!

    Carly

    • Yair Altman says:

      @Carly – What you describe sounds like the way non-editable text is displayed. Maybe these cells are non-editable? try making the columns editable and recheck.

      R2012a made changes in the way that uitables (even the old uitable) display data, this may well be one of these changes. Most of these changes can be solved or bypassed, but it could take some time to figure out exactly what to do. If this is important to you and you would like my consulting help, please contact me by mail.

  5. berlouu says:

    Hi Yair,

    Thanks for your contribution. I have managed to use it successfully, but once I changed the background colour, it would not let update the table data anymore. Have you got any idea for that? Thanks very much.

    Berloou

  6. Pingback: Multi-line uitable column headers | Undocumented Matlab

  7. David Goldsmith says:

    Hi, Yair, and thanks! What if I have the opposite problem, namely, the original figure width is too small for the default column witdths–how can I auto-widen the figure so that even the widest of my columns are not cut off? (My guess is that I have to grab the underlying java Figure and Panel objects into which I’ve placed my table and then use autoresize properties they have, yes? Help me out: what are they called?) Thanks again!

    • Yair Altman says:

      @David – there’s no magic wand here that I know. You could sum the table column widths, and then resize your containing panel and figure accordingly.

    • David Goldsmith says:

      Thanks, Yair, but how do I get the table colum table widths?
      (get(myTable, ‘Columnwidth’) simply returns ‘auto’)?

    • Yair Altman says:

      You could use jTable.getWidth directly, or access each of the columns separately as follows:

      totalWidth = 0;
      for colIdx = 1 : jTable.getColumnCount
         totalWidth = totalWidth + jTable.getColumnModel.getColumn(colIdx-1).getWidth;
      end
    • David Goldsmith says:

      Thanks again, Yair; I assume you mean jTable.getColumnCount?

    • Yair Altman says:

      @David – indeed, corrected

  8. jeff says:

    Yair,

    I bought your book, Undocumented Matlab, and really like it. I’ve looked at some of the formatting options you discuss. However, I haven’t seen anything on alignment of the text/data within each cell. I would like to center the data in some cells but don’t see a method for doing so. Do you know if this is possible? Thanks.

    Jeff

    • Yair Altman says:

      @Jeff – you need to use the cell renderer for this. If you need specific alignments in specific cells, then you would need to write a dedicated renderer class

  9. jeff says:

    Hi.Yair

    I am using MATLAB to make uitable. I have a proble on the uitable background color setting , in matlab there is a setting for row background color, but no setting for uitbale background color. Some times i need a big uitable frame but less rows , then the empty part of uitable under rows is gray , it is not good color for me , i want to change it .

    Could you give some tips on it?

    Best regards,
    Jeff

  10. Edmund says:

    Hi Yair,
    I have built a uitable using GUIDE in Matlab, but I want to customise color into it, is it possible to implement your code into GUIDE? If so, how can I do that? Thanks.

    Regards,
    Edmund

  11. jose antonio says:

    Hello Yair and thanks, how could I resize the table when I resize the panel that contain it?

    Example:

    S.fh = figure('units','pixels',...
                  'position',[100 100 752 350],...
                  'menubar','none',...
                  'name','helpTrader',...
                  'numbertitle','off',...
                  'resize','on');
    S.mtable = uitable( 'position',[25 25 700 280] );
    S.jScroll = findjobj(S.mtable); % objeto java
    S.jTable = S.jScroll.getViewport.getView;
    S.jTable.setAutoResizeMode(S.jTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); % auto resizing
  12. Thanks Yair. I tried using the cellrenderer that you posted. Works great within MATLAB. However, I am getting an error when I try to compile it into an application. Copied below.

    ——
    'Undefined function 'ColoredFieldCellRenderer' for input arguments of type 'java.awt.Color'
    ——

    • Yair Altman says:

      @JavaIlliterate – you need to include the ColoredFieldCellRenderer.zip as an external file to your deployment project, and then call javaaddpath to make your Matlab program aware of it.

      Alternatively, you can include the filepath of the zip file in a claspath.txt file that you can include as another external file in your deployment, but I would suggest against this because it ties your installation to a specific (absolute) folder path.

  13. JKen says:

    Hi Yair,

    Thanks a lot for putting this together – appears to be a really nice utility. I have got most of what I want working for a table generated via GUIDE, but a few problems remain:
    - when coloring cell foreground, coloring appears only to take effect when font is also modified via HTML strings (note that this code is in separate functions, so fairly sure of this) [The bulk of the cells are currently without HTML strings - using only where text effects required]
    - HTML formatted cells are shown by default left-aligned, with standard cells right-aligned. Is there any way to set alignments consistently right or centre without adding this to the HTML?

    Wondered if you had any thoughts

    • Yair Altman says:

      @JKen – these are explained in my uitable customization report and in my Matlab-Java programming book.

    • JKen says:

      Hi Yair,

      apologies to bug you again, but I have the book with me and can’t seem to find the section of interest. Specifically, I feel that I have followed the code examples correctly, yet still see that foreground color only takes effect if cell text also modified to include HTML tags.

      I also notice a Java null pointer exception when pressing arrow up whilst on cell 1,1 (but no other cell). I expect this to be a zero versus one index that has been missed somewhere, but find it odd that it would only affect first cell and wondered if you had seen it before. Without these fixes, not too happy to call my code complete

      Thanks

    • JKen says:

      Looks likely to me that these are both functions of the Matlab version (R2012b). I may of course be wrong, but feel that I have replicated code above in simple test function that still displays both effects. I could put up with the need to set foreground colors via HTML (background color is the more difficult) but producing errors when moving to cell 1,1 is not pretty. Note also that I see same effect as described by Carly (text appears non-editable) but yet the cell contents can be edited [as per example, 'ColumnEditable' set to false, although I seem to remember your comment that this was perhaps disregarded]

    • Yair Altman says:

      @JKen -

      1) for the bgcolor, look at page 162. In short this is due to what is in my eyes a serious design flaw in the new uitable that needs a new table model to work-around.
      2) for the Java exception, look at page 160. All Java indexes (inc. row and column numbers) are 0-based, not 1-based as in Matlab. You need to convert accordingly in your callback functions.

    • JKen says:

      Hi Yair,
      Thanks for the info. I did notice the change to default datamodel in your example and used same code in mine. Background color is settable, but foreground color not.
      For the Java exceptions, I agree that the most likely reason at first sight would be incorrect indexing. I do have a couple of issues with this:
      * My test function is now effecitvely a copy of your code above (including index handling)
      * Background & foreground colors are set at expected indexes
      * Selected cell highlighting is at expected index
      * It is only when selecting cell 1,1 that this problem presents

      I really do think that this problem presents in R2012b and not earlier versions (not sure about R2009) and that the code outlined above will trigger these in R2012b

    • Yair Altman says:

      @JKen – It is possible that you’ve discovered a bug in R2012b, but it could also possibly be due to something in your code. Without detailed debugging, it is hard to say for sure. Public blog comments are not an appropriate or suitable mechanism for in-depth program debugging, so I’m afraid that you’ll need to continue by yourself from this point. If you’d like my assistance (as a paid consultant), please email me using the link at the top-right of this page.

  14. JKen says:

    Fair enough. Thanks for the help so far – does look to be a nice utility

  15. Reza says:

    Hi dear Yair
    In the javatable there are some properities like:
    SelectionBackground
    SelectionForeground
    I tried to change these like

    set(jtable,'SelectionBackground',[1,0,0])
    set(jtable,'SelectionBackground',[1,0,1])

    But it does not change at all…
    What should I do to fix this problem?

  16. Dermot says:

    Hi Jair,
    thanks for this post. I am trying to combine this with the uitable sorting (http://undocumentedmatlab.com/blog/uitable-sorting/) but I find that when I sort the table the cells colours stay in the same place so that they don’t have any relation to the cell values anymore. Is there sone jtable property I can set so that the formats “move” with the value when I sort?

    • Yair Altman says:

      @Dermot – you could implement a smarter cell-color CellRenderer that looks not at the current row, but at the actual data row, using jtable.getModel.getActualModel. The same is true if you implement filtering that removes some rows from the current view.

  17. Pingback: Parsing mlint (Code Analyzer) output | Undocumented Matlab

Leave a Reply

Your email address will not be published. Required fields are marked *

*

<pre lang="matlab">
a = magic(3);
sum(a)
</pre>