In the past year, readers of this blog have used its search box thousands of times. Can you guess what the top search terms are?
It turns out that 7 of the top 15 search terms relate to tables, trees and tab-panes.
These items are related in being standard GUI elements that unfortunately have very lacking support in Matlab. They all have corresponding functions in the %matlabroot%/toolbox/matlab/uitools folder, which was already introduced here as containing many unsupported GUI functions. Specifically, uitable for tables (this became supported in R2008a, but even the supported version has many important undocumented aspects); uitree and uitreenode for trees; and uitab and uitabgroup for tab-panes, which are today’s subject. Future articles will describe tables, trees and tab-panes in more detail.
uitab & uitabgroup
Like most other uitools, the uitab and uitabgroup functions are semi-documented, meaning that they have no support or doc-page, but do have readable help sections within their m-files. In our case, edit the uitab.m and uitabgroup.m files to see their help section.
Available since 2004 (R14 SP2, aka 7.0.4), Matlab’s uitabgroup uses the Matlab Java widget com.mathworks.hg.peer.UITabGroupPeer, which extends the standard javax.swing.JTabbedPane. Unlike uitable and uitree, which use actual Java objects to both store and present the data, uitabgroup only sets up the Java object to display the tabs, whereas the tab contents themselves are placed in entirely unrelated Matlab uicontainers. Matlab uses very clever double-booking to keep the Java and Matlab objects synchronized. The ability to “switch” tabs is actually a deception: in reality, a listener placed on the SelectedIndex property of the tab group causes the relevant Matlab container to display and all the rest to become hidden. Other listeners control containers’ position and size based on the tab group’s. Adding and removing tabs uses similar methods to add/remove empty tabs to the JTabbedPane. Read uitabgroup‘s schema.m for details.
A drawback of this complex mechanism is the absence of a single customizable Java object. The benefit is that it allows us to place any Matlab content within the tabs, including plot axes which cannot be added to Java containers. Had uitabgroup been a Java container, we could not add axes plots or images to its tabs. In my humble opinion, Matlab’s tab implementation is an ingenious piece of engineering.
Here’s a simple tab-group adapted from uitabgroup‘s help section:
hTabGroup = uitabgroup; drawnow; tab1 = uitab(hTabGroup, 'title','Panel 1'); a = axes('parent', tab1); surf(peaks); tab2 = uitab(hTabGroup, 'title','Panel 2'); uicontrol(tab2, 'String','Close', 'Callback','close(gcbf)');
(recent Matlab releases throw a warning when using this code: either add the ‘v0’ input arg to uitabgroup and uitab calls, or suppress the MATLAB:uitabgroup:MigratingFunction warning)
Here, the returned uitabgroup object hTabGroup is actually a Matlab container (deriving from uiflowcontainer) that always displays two elements: the Java tab-group, and the active Matlab uicontainer (the active tab’s contents). Understanding this, hTabGroup’s FlowDirection property becomes clear. However, it is better to use hTabGroup’s TabLocation property, which accepts ‘top’, ‘bottom’, ‘left’ and ‘right’:
Another hTabGroup property of interest is Margin, which sets the margin in pixels before each of the displayed elements – not just between them as might be expected: Increasing Margin (default=2 pixels) increases the gap between the tab group and the active tab’s contents, but also the gap between the tab group and figure edge:
Tabs can be selected programmatically, by setting hTabGroup’s SelectedIndex property. Reading this property is useful when setting tab-selection callbacks using the SelectionChangeFcn property:
set(hTabGroup,'SelectionChangeFcn',@myCallbackFcn); set(hTabGroup,'SelectedIndex',2); % activate second tab
Edit Oct 27 2010: R2010b made a few changes to the hTabGroup properties: SelectedTab has been added (holds the handle of the selected tab, rather than its index as SelectedIndex; note that SelectedTab was added as a hidden property for some unknown reason, probably a programming mistake); the tab BackgroundColor cannot be modified (I’ll show how to bypass this limitation in a near-future article); SelectionChangeFcn callback and the SelectionChanged event have changed their names to SelectionChangeCallback and SelectionChange respectively. Note that this is one of the very rare occasions in which MathWorks have taken the trouble to notify users about changes to one of their undocumented/unsupported functions. They should be commended for this since it helps us Matlab users make better use of the product.
Additional control over the tab group’s behavior can be achieved by customizing the underlying Java object. This object is not directly exposed by uitabgroup, but can be found using the FindJObj utility, or via the hidden ApplicationData (this alternative only works on R2014a or earlier!). Remember that Java objects use 0-based indexing so tab #1 is actually the second tab. Also remember that HTML is accepted just as in any other Swing-based label:
% Get the underlying Java reference using FindJObj jTabGroup = findjobj('class','JTabbedPane'); % A direct alternative for getting jTabGroup (only works up to R2014a!) jTabGroup = getappdata(handle(hTabGroup),'JTabbedPane'); % Now use the Java reference to set the title, tooltip etc. jTabGroup.setTitleAt(1,'Tab #2'); jTabGroup.setTitleAt(1,'<html><b><i><font size=+2>Tab #2'); jTabGroup.setToolTipTextAt(1,'Tab #2'); % Disabling tabs can only be done using the Java handle: jTabGroup.setEnabledAt(1,0); % disable only tab #1 (=2nd tab) jTabGroup.setEnabled(false); % disable all tabs
A future post will describe tab customization, including fonts, colors, icons and even addition of close buttons as in modern web browsers.
tabdlg is a related semi-documented and unsupported uitool that, like uitabgroup, creates a tabbed user interface. However, unlike uitabgroup, tabdlg uses plain-vanilla Matlab, without reliance on Java (well, actually all Matlab GUI controls ultimately rely on Java, but tabdlg does not use any Java beyond that). The end result looks less professional than uitabgroup, but it works even when Java does not.
tabdlg has an extensive help section, so it will not be detailed here. In brief, the input parameters specify the tab labels, dimensions, offsets, callbacks, font, default tab, sheet dimensions and parent figure. Here is a sample usage, taken from tabdlg‘s help section. This code is executed whenever tabdlg is invoked without any input arguments:
File Exchange alternatives
There are many implementations of tab panels in the Matlab File Exchange. Matlab’s official Desktop Blog had an article about one specific example, which was that week’s Peek of the Week, and relied on adjacent buttons that are easy to implement, but in my personal opinion are a far cry from our expectations of a tab panel.
Better FEX utilities are: Multiple Tab GUI, Highlight Tab Objects easily, and best of all: uitabpanel or TabPanel Constructor.
Another very recent submission was this week’s POTW. This utility gives a professional (although somewhat non-standard) look, and is very easy to program – an excellent utility indeed.
All of the numerous tab-panel FEX utilities, as well as the fact that tab-panels are one of the most searched-for terms in this website, indicate the Matlab community’s desire to have supported native-looking tab-panel GUI in Matlab. Perhaps after 6 years it is time to bring uitab and uitabgroup into the light?
Addendum Oct 3 2014: the uitab and uitabgroup functions have finally become fully supported and documented in Matlab version 8.4 (R2014b). They remain practically unchanged from what I’ve described in this article, more than four years earlier.
Have you noticed that MATLAB gives an error when setting the uitabgroup BackgroundColor to ‘none’? It does work if I provide a “real” color string, such as ‘red’. Any thoughts?
??? No constructor ‘java.awt.Color’ with matching signature found.
Error in ==> uitools.uitabgroup.schema>backgroundColorCallback at 192
javapeer.setControlBackgroundColor(java.awt.Color(col(1), col(2), col(3)));
Warning: Error occurred while evaluating listener callback.