uitable is probably the most complex basic GUI controls available in Matlab. It displays data in a table within a figure, with settable properties as with any other Matlab Handle-Graphics (HG) control. After many years in which the uitable was available but semi-documented and not officially supported in Matlab, it finally became fully documented and supported in R2008a (aka Matlab 7.6). At that time its internal implementation has changed from a MathWorks-developed Java table to a JIDE-based Java table (another JIDE-derived table was described here last year). Since R2008a, both versions of uitable are available – the old version is available by adding the ‘v0’ input arg.
Matlab’s uitable exposes only a very limited subset of functionalities and properties to the user. Numerous other functionalities are available by accessing the underlying Java table and hidden Matlab properties. Today I will describe a very common need in GUI tables, that for some unknown reason is missing in Matlab’s uitable: Sorting table data columns.
Last week I explained how we can modify table headers of an ActiveX table control to display sorting icons. In that case, sorting was built-in the control, and the question was just how to display the sorting arrow icon. Unfortunately, Matlab’s uitable does not have sorting built-in, although it’s quite easy to add it, as I shall now show.
Old uitable sorting
The old uitable is the default control used until R2007b, or that can be selected with the ‘v0’ input arg since R2008a. It was based on an internal MathWorks extension of the standard Java Swing JTable – a class called com.mathworks.widgets.spreadsheet.SpreadsheetTable
.
Users will normally try to sort columns by clicking the header. This has been a deficiency of JTable for ages. To solve this for the old (pre-R2008a) uitable, download one of several available JTable sorter classes, or my TableSorter class (available here). Add the TableSorter.jar file to your static java classpath (via edit('classpath.txt')
) or your dynamic classpath (javaaddpath('TableSorter.jar')
).
% Display the uitable and get its underlying Java object handle [mtable,hcontainer] = uitable('v0', gcf, magic(3), {'A', 'B', 'C'}); % discard the 'v0' in R2007b and earlier jtable = mtable.getTable; % or: get(mtable,'table'); % We want to use sorter, not data model... % Unfortunately, UitablePeer expects DefaultTableModel not TableSorter so we need a modified UitablePeer class % But UitablePeer is a Matlab class, so use a modified TableSorter & attach it to the Model if ~isempty(which('TableSorter')) % Add TableSorter as TableModel listener sorter = TableSorter(jtable.getModel()); jtable.setModel(sorter); sorter.setTableHeader(jtable.getTableHeader()); % Set the header tooltip (with sorting instructions) jtable.getTableHeader.setToolTipText('<html> <b>Click</b> to sort up; <b>Shift-click</b> to sort down<br /> ...</html>'); else % Set the header tooltip (no sorting instructions...) jtable.getTableHeader.setToolTipText('<html> <b>Click</b> to select entire column<br /> <b>Ctrl-click</b> (or <b>Shift-click</b>) to select multiple columns </html>'); end |
New uitable sorting
The new uitable is based on JIDE’s com.jidesoft.grid.SortableTable
and so has built-in sorting support – all you need to do is to turn it on. First get the underlying Java object using my FindJObj utility:
% Display the uitable and get its underlying Java object handle mtable = uitable(gcf, 'Data',magic(3), 'ColumnName',{'A', 'B', 'C'}); jscrollpane = findjobj(mtable); jtable = jscrollpane.getViewport.getView; % Now turn the JIDE sorting on jtable.setSortable(true); % or: set(jtable,'Sortable','on'); jtable.setAutoResort(true); jtable.setMultiColumnSortable(true); jtable.setPreserveSelectionsAfterSorting(true); |
Note: the Matlab mtable
handle has a hidden Sortable property, but it has no effect – use the Java property mentioned above instead. I assume that the hidden Sortable property was meant to implement the sorting behavior in R2008a, but MathWorks never got around to actually implement it, and so it remains this way to this day.
A more detailed report
I have prepared a 45-page PDF report about using and customizing Matlab’s uitable, which greatly expands on the above. This report is available for $25 here (please allow up to 48 hours for email delivery). The report includes the following (more details here):
- comparison of the old vs. the new uitable implementations
- description of the uitable properties and callbacks
- alternatives to uitable using a variety of technologies
- updating a specific cell’s value
- setting background and foreground colors for a cell or column
- using dedicated cell renderer and editor components
- HTML processing
- setting dynamic cell-specific tooltip
- setting dynamic cell-specific drop-down selection options
- using a color-selection drop-down for cells
- customizing scrollbars
- customizing column widths and resizing
- customizing selection behavior
- data sorting (expansion of today’s article)
- data filtering (similar to Excel’s data filtering control)
- merging table cells
- programmatically adding/removing rows
- numerous links to online resources
- overview of the JIDE grids package, which contains numerous extremely useful GUI controls and components
Hello Yair,
Without knowing your post, i have posted about this subject at Matlab Newsreader. 🙂
https://www.mathworks.com/matlabcentral/newsreader/view_thread/310934/
However i still couldnt find a way to get the selected cell information. After sorting the data, I try to get the selected cell position (relative to table) with “eventData.Indices” and using the getSortedRowAt with column indice, it is supposed to give me the position of selected cell relative to the original data. My code is;
jtable.getSortedRowAt(eventData.Indices(1))
The results are incorrect most of the time unfortunately. Do i make any mistake?
@Arda – this is answered in the report…
Yair thanks for the guide, I have figured it out.
WOW ! thanks Yair: I was rightly looking for this week an easy way to achieve this task : sorting an uitable.
You gave me the answer. Thanks again!
Maybe I’m not doing this right, but the new JIDE uitable sort is sorting the values as string only. Even though it is displayed as numbers, right justified, it sorts 3,10,30 as 10,3,30.
Okay it looks like the the new uitable uses default table model, getColumnClass always returns java.lang.Object, so sorting would not be correct for numbers fields even if column format is set to numeric. If there is no reasonably easy way to change this, it significantly reduces the usefulness the new uitable sorting capability.
A workaround for sorting numbers in uitable is detailed in the report…
I’m feeling dumb. I read through the report, and can’t seem to find any reference to the workaround for dealing with numbers with the new uitable.
@Yun – I believe that you read the blog post, not the report. The report is a 35-page document that is available for a small fee here.
When I have a large number of rows in the uitable, sorting doesn’t function correctly. Do you run into this problem? If yes, is there a way to fix it?
System info: Windows 7 64-bit, Matlab r2011a 64-bit
@Drew – strange indeed. Looks like a JIDE bug to me… Maybe this is the reason for sorting not being exposed in Matlab.
I have the same problem with large number of rows. Moreover, the sorting doesn’t comply with the locale (I’m french canadian). In the following example, ‘Éric’ and ‘Eric’ should be sorted after ‘Aude’ and before ‘Marc’.
Using jTable.setAutoCreateRowSorter(true) comply with the locale but do not allow for multi column sorting…
As we can change the column-format property to checkbox, popupmenu options in the uitable, I need help for changing the column-format property to radio-button.
Help me regarding this issue……….
[…] 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 […]
Hi
For some strange reason, the ‘new uitable sorting’ isn’t working on windows 7 64 bit. It works fine on lion.
I get the following error:
No appropriate method, property, or field getViewport for class
handle.handle.
Error in MPMSimPre>MPMSimPre_OutputFcn (line 349)
jtable = jscrollpane.getViewport.getView;
Error in gui_mainfcn (line 265)
feval(gui_State.gui_OutputFcn, gui_hFigure, [], gui_Handles);
Error in MPMSimPre (line 280)
gui_mainfcn(gui_State, varargin{:});
Please advise.
Matlab Version: R2011b Win 64bit
@Javveer – this is because findjobj doesn’t find the table reference for some unknown reason. Try playing around with different parameters, maybe move the table a bit in the figure, maybe download the latest version of findjobj. If all this still doesn’t work, you can either debug findjobj step-by-step with the debugger, or use a different sorting mechanism, or implement a pure-Java table. As a last resort, you can always use my consulting skills…
@Yair
Thank you for the suggestions. Unfortunately none of the simple solutions suggested worked. On snow leopard, placing the sorting code below the one that updates the table seems to do the trick. The only OS the code works flawlessly from within OutputFcn is Lion.
Ciao Yair,
first, thanks you for your fantastic website!
I’m using the JIDE-based Java table, your example works perfectly. There is only one problem when I try to use a specific filter: “condition”->”is in”->”value(s)”. It opens a checkbox list but when I click on one checkbox, I get a very long error in my command window starting with:
and of course the filtering does not work. This is a shame because this kind of filter is what I was looking for!
Have you got any idea about how to fix this problem?
Thank you very much for your help.
Seb
@Sebas – I’m not sure exactly how you got there but in any case it looks like something that requires some investigation. If you’d like me to check this out for you, contact me by email for a short consulting proposal.
Is it me or doubles are not properly sorted by the new uitable? In decreasing order (arrow pointing down), I have:
750.1248
671.5008
2.1361e+03
I double-checked and the data is doubles (…), not strings. Integers don’t exhibit this problem.
@Luc – this is correct. Doubles are sorted lexically (’12’ < ‘6’), not numerically (12 > 6). My uitable report has some workarounds.
Hi Yair,
I am using Matlab 2014b and created a Uitable that I want to display in a Jpanel. I tried to get the underlying Java object handle of the uitable using the functions you suggested above:
Unfortunately I get the following error:
Can you please help to come up with this problem? Thanks!
Regards,
Ange Laure
@Ange –
mtable.getTable
only works on the old (pre-R2008a) uitable; with the new (R2008a onward) uitable you need to use the findjobj utility to get the underlying Java object.You can read all about it in my uitable customization report.
Hi Yair,
Like you mention that the workaround to sort numerically (rather than lexically) is mentioned in your uitable report, is it mentioned in your ‘Undocumented secrets of MATLAB’ book? Or do I need to get that uitable report too specifically for this?
Many thanks for all your articles. You had been a life saver so many times.
Cheers…
@Amit – unfortunately I only refer to this issue in my report, not the book. My Matlab-Java book was published 4.5 years ago and in the meantime I expanded the coverage of uitable in my uitable customization report, so it now contains more contents than the book, including this specific feature. On the other hand, the book includes a lot of other content that is not related to uitable. Also, the report is in full-color PDF format, whereas the book is not. So while there is overlap between the book and the report, they are different in important ways, and complement each other.
Are you working on new editions of both of your books? I would love get updated editions. I am going for your uitable report meantime. Thanks for your help.
Hi Yair,
I tried using getSelectionModel and Valuechangedcallback but with a single mouse click function is getting executed multiple times with same data and finally giving output and an error saying “exception in thread AWT=EventQueue-0”
can you please help with this
@Praneeth – you need to handle this programmatically, within your Matlab callback function. For example:
Also look at the various mechanism to avoid callback reentrancy here: http://undocumentedmatlab.com/blog/controlling-callback-re-entrancy
@Yair – I tried it always value in Valueisadjusting is 0 but still its running in a loop and finally throwing the error “exception in thread AWT=EventQueue-0”.
Also can you tell me in which page did u mention about sorting numerically with JIDE. i read through your undocumented matlab book but didint find
@Praneeth – You did not listen to what I told you: you need to prevent callback reentrancy yourself, in your callback function. Multiple ways to do this are discussed in the webpage that I linked in my previous answer.
As for numeric sorting, I did not discuss this issue in my book. You basically need to create a custom data model Java class that handles this (or contract me to do it for you).
To make it more clear its running multiple times on a single cell value
@Yair. Thanks a lot for the reply.
Callback reentrancy is now controlled but still i am getting the java exception “exception in thread AWT=EventQueue-0”
Anyway to avoid this?
Hi,Yair
I hava a question.when I use jtable.setModel(javax.swing.table.DefaultTableModel(Data,headers)to updata the data in old matlab uitable;I find I cannot use data = cell(mtable.getData)to get the editored data I find use jtable.getModel().getDataVector() can get the data in java.util.Vector .But how I let the the java.util.Vector Data tranfer a cell-style data I try use cell(jtable.getModel().getDataVector()),but the result is [ 1000 java.util.Vector];
Thanks
data = cell(mtable.getData)
should be used but you might need to pause(0.01) to let the data updates propagate from the jtable model to the mtable object.THanks ,it really worked when I didn’t use ColoredFieldCellRenderer.
it may be the question I use the ColoredFieldCellRenderer to Rendering the cell ,and it shows this Exception :
Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException
at ColoredFieldCellRenderer.getTableCellRendererComponent(ColoredFieldCellRenderer.java:101)
at javax.swing.JTable.prepareRenderer(Unknown Source)
at javax.swing.JTable.getToolTipText(Unknown Source)
at javax.swing.ToolTipManager$insideTimerAction.actionPerformed(Unknown Source)
at javax.swing.Timer.fireActionPerformed(Unknown Source)
at javax.swing.Timer$DoPostEvent.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
I find the jtable.getModel().getDataVector() can shows correct data in jtable.getModel().getDataVector(),while it cannot propagate from the jtable model to the mtable object。
@shi – this is an unhandled case in the
ColoredFieldCellRenderer
code. You have the source code for this class – it is quite simple and you can modify it in a which that will handle sorted data rows.Hi Yair
How can I make the table.Data to be update after i’m sorting a table as like as you described above?
Because I noticed that after i’m sorting a table the table.Data remains the same as before i sorted the table and actually disconnect what the table showing to the user.
TNX
Jack
@Jack – sorting only affects the way that the table-model data is displayed, it does not affect the data itself. You can get the model-to-view mapping using this:
Note that java indices start at 0 (not 1 as in Matlab), hence the need for the -1 and +1 in the code snippet above.
When the table is not sorted,
displayedRowIndex
will be the same asmodelRowIndex
; when sorted it will return a different index.Hi Yair
Thank you very much for your answer.
Can you explain me please what is the meaning of the index that getSortedRowAt is returning? I noticed it is’nt the row index before the table sorted.
Thanks,
Jack
jtable.getSortedRowAt(rowIndex) returns the display row index for a specified data model row;
jtable.getActualRowAt(rowIndex) returns the data model row index for a specified display row.
Thank! It’s helped me a lot!
Hi Yair,
I think I have a new problem, maybe you haven’t seen!
I’m using a uitable to make an interactive name builder. Basically, I’m creating a table with dynamic column names. The user can then change the order to make a new permutation.
The problem is I can’t figure out a callback that will fire when the columns are rearranged!
Do you have any thoughts? Ever seen anything similar?
Again, many thanks for a great blog.
Best,
Meade
@Meade – I do not have an immediate answer, but it’s quite possible that a solution can be found. If you’d like me to investigate this (for a consulting fee) then email me.
Thank you so much. This works well for UITables embedded in a traditional figure but I’m having issues getting findjobj to work when the UITable is embedded in a UIFigure, it just returns an empty array. (I have an application build in App Designer.) Is there another way to get the Java handle to the UITable when it’s in a UIFigure?
Thanks,
Dan
@Dan – uifigures are based on HTML and JavaScript, they are basically nothing more than a webpage displayed within a browser window. In comparison, legacy figures are based on Java desktop windows. So any customization that works on the Java-based figures and relies on Java (including uitable customizations) will never work in uifigures, and you cannot get the Java handle of uifigure components because they’re not based on Java.
For details on uifigure customizations, refer to the list of posts that have the uifigure tag.