Uitab colors, icons and images

A few months ago I published a post about Matlab’s semi-documented tab-panel functionality, where I promised a follow-up article on tab customizations. A reader of this blog asked a related question earlier today, so I decided it’s about time I fulfilled this promise.

As with most Matlab controls, the underlying Java component enables far greater customization than possible using plain Matlab. Today I will show three specific customizations. We start with a basic tab group, and get the underlying Java component:

% Prevent an annoying warning msg
warning off MATLAB:uitabgroup:OldVersion
 
% Prepare a tab-group consisting of two tabs
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)');
 
% Get the underlying Java reference (use hidden property)
jTabGroup = getappdata(handle(hTabGroup),'JTabbedPane');

Foreground & background tab colors

We can set the tab font color using setForeground() and setForegroundAt(), or via HTML. Note that setForegroundAt() overrides anything set by setForeground(). Also remember that Java uses 0-based indexing so tab #1 is actually the second tab:

% Equivalent manners to set a red tab foreground:
jTabGroup.setForegroundAt(1,java.awt.Color(1.0,0,0)); % tab #1
jTabGroup.setTitleAt(1,'<html><font color="red"><i>Panel 2');
jTabGroup.setForeground(java.awt.Color.red);

Unfortunately, the corresponding setBackgroundAt(tabIndex,color) method has no visible effect, and the Matlab-extended tabs keep their white/gray backgrounds. A similar attempt to modify the tab’s BackgroundColor property fails, since Matlab made this property unmodifiable (=’none’). A simple solution is to use a CSS background:

% Equivalent manners to set a yellow tab background:
jTabGroup.setTitleAt(0,'<html><div style="background:#ffff00;">Panel 1');
jTabGroup.setTitleAt(0,'<html><div style="background:yellow;">Panel 1');

uitabgroup with non-default forground and background tab colors and fonts

uitabgroup with non-default forground and background tab colors and fonts

We can set the foreground text color using the CSS color directive. Similarly, we can also set a background gradient image for the tabs, using the CSS background-image directive. Which leads us to our next customization:

Icon images

Icons and sub-components can be added to the tabs. Unfortunately, for some reason that I do not fully understand, jTabGroup.setIconAt() has no apparent effect. The solution is to set our own custom control as the requested tab, and add our icon (or other customizations) to it. Here is a simple example:

% Add an icon to tab #1 (=second tab)
icon = javax.swing.ImageIcon('C:\Yair\save.gif');
jLabel = javax.swing.JLabel('Tab #2');
jLabel.setIcon(icon);
jTabGroup.setTabComponentAt(1,jLabel);	% Tab #1 = second tab
 
% Note: icon is automatically grayed when label is disabled
jLabel.setEnabled(false);
jTabGroup.setEnabledAt(1,false);  % disable only tab #1

tab with a custom icon (enabled)
tab with a custom icon (enabled)

tab with a custom icon (enabled & disabled)

Close buttons

Now let’s try a more complex example, of adding a close (‘x’) button to one of the tabs. Generalizing this code snippet is left as an exercise to the reader:

% First let's load the close icon
jarFile = fullfile(matlabroot,'/java/jar/mwt.jar');
iconsFolder = '/com/mathworks/mwt/resources/';
iconURI = ['jar:file:/' jarFile '!' iconsFolder 'closebox.gif'];
icon = javax.swing.ImageIcon(java.net.URL(iconURI));
 
% Now let's prepare the close button: icon, size and callback
jCloseButton = handle(javax.swing.JButton,'CallbackProperties');
jCloseButton.setIcon(icon);
jCloseButton.setPreferredSize(java.awt.Dimension(15,15));
jCloseButton.setMaximumSize(java.awt.Dimension(15,15));
jCloseButton.setSize(java.awt.Dimension(15,15));
set(jCloseButton, 'ActionPerformedCallback',@(h,e)delete(tab2));
 
% Now let's prepare a tab panel with our label and close button
jPanel = javax.swing.JPanel;	% default layout = FlowLayout
set(jPanel.getLayout, 'Hgap',0, 'Vgap',0);  % default gap = 5px
jLabel = javax.swing.JLabel('Tab #2');
jPanel.add(jLabel);
jPanel.add(jCloseButton);
 
% Now attach this tab panel as the tab-group's 2nd component
jTabGroup.setTabComponentAt(1,jPanel);	% Tab #1 = second tab

tab with an attached close button

tab with an attached close button

Next week’s article will conclude the series on Matlab’s uitab. Any particular customization you are interested in? Please do post a comment.

Addendum Oct 3 2014: the uitab and uitabgroup functions have finally become fully supported and documented in Matlab version 8.4 (R2014b). However, the Java-based customizations shown in this article are still unsupported and undocumented, although they remain practically unchanged from what I’ve described in this article, four years earlier.

Related posts:

  1. Uitab customizations This article shows several customizations that can be done to Matlab's undocumented tab-panels functionality...
  2. Tab panels – uitab and relatives This article describes several undocumented Matlab functions that support tab-panels...
  3. Setting system tray icons System-tray icons can be programmatically set and controlled from within Matlab, using new functionality available since R2007b....
  4. Images in Matlab uicontrols & labels Images can be added to Matlab controls and labels in a variety of manners, documented and undocumented. ...
  5. Uitable cell colors A few Java-based customizations can transform a plain-looking data table into a lively colored one. ...
  6. 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....

Categories: GUI, Icons, Java, Medium risk of breaking in future versions, Semi-documented function

Tags: , , , , , ,

Bookmark and SharePrint Print

18 Responses to Uitab colors, icons and images

  1. Alex says:

    If I execute the following code, the Tab with the icon is not greyed out. It is obviously disabled because I cant click on it, but it looks exactly like an enabled tab. (Icon and Label ar not grey).

    % Prepare a tab-group consisting of two tabs
    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)');
     
    % Get the underlying Java reference (use hidden property)
    jTabGroup = getappdata(handle(hTabGroup),'JTabbedPane');
     
    % Add an icon to tab #1 (=second tab)
    icon = javax.swing.ImageIcon('Find.gif');
    jLabel = javax.swing.JLabel('Tab #2');
    jLabel.setIcon(icon);
    jTabGroup.setTabComponentAt(1,jLabel);	% Tab #1 = second tab
     
    % Note: both label &amp; icon automatically grayed when disabled
    jTabGroup.setEnabledAt(1,false);  % disable only tab #1

    If I comment the paragraph titled with “% Add an icon to tab #1″, the tab is greyed out properly (without icon). You wrote that icons are automatically greyed out, but I can’t get it to work. Does this code work on your computer?

  2. john says:

    Hi,

    Im trying to make the title of tabs bold but am having some trouble using html doing it. I tried using

    jTabGroup.setForeground(java.awt.Font.BOLD);

    But this doesnt seem to work, any suggestions? Thanks

  3. Mark says:

    Hi,

    Thank you for this great “un”documentation! It found instant use in my GUI. :-)
    I did realize that adding a jLabel together with a close button makes the tab look a bit odd as the label then takes the color of the figure background instead of the tab itself (which can also be seen on the above image of the tab with closebutton). I tried to find the source of this behaviour and found that adding either jLabel or close button would lead to it. In the above picture of a jLabel with an icon however everything looks normal….
    Anyhow, i solved the problem by setting the jPanel ‘Opaque’-property to ‘off’, i.e.:

    set(jPanel.getLayout, 'Hgap',0, 'Vgap',0);  %default gap=5px
    set(jPanel,'Opaque','off');

    Again thanks for the documentation, keep that good stuff coming!

    Greetz
    -Mark

  4. Etienne says:

    Hi
    I really find your blog extremely useful for our GUI development.
    In your close button example, you use the callback

    set(jCloseButton, 'ActionPerformedCallback',@(h,e)delete(tab2));

    I have no clue of what the @(h,e) construction does. Could you explain ?

    • @Etienne – this is the standard way that Matlab callbacks are defined: h is the callback’ed object (in this case, jCloseButton), e is the eventData object that holds information about the callback event. A full explanation is available here.

      In this case, @(h,e) is simply an inline definition of a simple function that accepts h and e, and does “delete(tab2)” (no need for either h or e in this particular case).

  5. Yigit Koyuncuoglu says:

    Hello Yair
    I have a question about using the uitree. As I understand uitree accepts generally figure handles. Is it possible to use an uitab handle instead of figure handle. For example, I have a GUI having four tabs, but I want to put an uitree object to only 2nd tab. Because uitree use figure handles, it appears in all tabs. Is it possible to solve this problem?

    • @Yigit – I explained how to do this in my post on uitree:

      uitrees are always created as a direct child of the containing figure, ignoring creation-time Parent values. However, the Parent property can be modified following the tree’s creation:

      [mtree, container] = uitree('v0', 'Root','C:\', 'Parent',tab1); % Parent is ignored
      set(container, 'Parent', tab1);  % fix the uitree Parent

      Note: you would probably also want to fix the container’s Position property, not just it’s Parent.

  6. Johan says:

    Hello Yair,

    I am using tabs aligned to the left.

    It seems like the title of the first tab added to hTabGroup sets the width of all tabs.

    Example:

    This will create very wide tabs

    %Create tabs
    hTabGroup = uitabgroup(gcf,'TabLocation','Left'); 
    tab1 = uitab(hTabGroup, 'title','1 -------------------------------------');
    a = axes('parent', tab1); surf(peaks);
    tab2 = uitab(hTabGroup, 'title','2');
    b = uicontrol(tab2, 'Style','pushbutton','String','Close', 'Callback','close(gcbf)');

    This will create very narrow tabs:

    %Create tabs
    hTabGroup = uitabgroup(gcf,'TabLocation','Left'); 
    tab1 = uitab(hTabGroup, 'title','1');
    a = axes('parent', tab1); surf(peaks);
    tab2 = uitab(hTabGroup, 'title','2 --------------------------------------');
    b = uicontrol(tab2, 'Style','pushbutton','String','Close', 'Callback','close(gcbf)');

    Is there a property that can be set to adjust the tab width?

    kind regards
    Johan

    • Johan says:

      Also, horizontal alignment of the title is set to centered, this looks very weird when titles of different length are used.

      Is there any way to change this?

    • @Johan – simply use TabLocation=’top’ or ‘bottom’. When you use ‘left’ or ‘right’ the tabs are all set to the same width, because otherwise they would not align one on top of the other. This is not a problem with top/left and so in those cases the tabs automatically use a dynamic width.

  7. Hiro says:

    In trying to make the title of tabs font size but I am having some trouble using html.

    jTabGroup.setForeground(java.awt.Fontsize.9)

    But this doesnt seem to work, any suggestions?
    Thanks

    • Yair Altman says:

      @Hiro – setForeground is used to set the foreground color, not the font. Try one of these alternatives:

      % Alternative #1 - HTML (pure Matlab)
      set(hTab, 'Title', 'tab title')
       
      % Alternative #2 - Java (requires *NON*-HTML tab title)
      jTabGroup = getappdata(handle(hTabGroup), 'JTabbedPane')
      jTabGroup.setFont(java.awt.Font('Arial',0,18))

      Note that HTML formatting of the title string overrides any Java-based customization.

  8. Mike says:

    Is it possible to implement this on a MATLAB uitabgroup?

    % First let's load the close icon
    jarFile = fullfile(matlabroot,'/java/jar/mwt.jar');
    iconsFolder = '/com/mathworks/mwt/resources/';
    iconURI = ['jar:file:/' jarFile '!' iconsFolder 'closebox.gif'];
    icon = javax.swing.ImageIcon(java.net.URL(iconURI));
     
    % Now let's prepare the close button: icon, size and callback
    jCloseButton = handle(javax.swing.JButton,'CallbackProperties');
    jCloseButton.setIcon(icon);
    jCloseButton.setPreferredSize(java.awt.Dimension(15,15));
    jCloseButton.setMaximumSize(java.awt.Dimension(15,15));
    jCloseButton.setSize(java.awt.Dimension(15,15));
    set(jCloseButton, 'ActionPerformedCallback',@(h,e)delete(tab2));

    Sorry if this is obvious, I’m new to MATLAB.

    • @Mike – I posted this code on this very page, so why would you think it was not possible???
      If you’re not sure how it works, simply run it in your Matlab. It won’t bite – I promise.

    • Mike says:

      I guess I wasn’t clear. What I was asking is how do you implement tho son a uitab grouped with uitabgroup to close SelectedTab. it looks like you enter set(jCloseButton, ‘ActionPerformedCallback’,@(h,e)delete(tab2)); and it will only delete the item ‘tab2′. Am I way off base here?

      Thanks for the quick reply.

    • @Mike – indeed: in this specific example the close-button will only close tab2. You need to set a similar ActionPerformedCallback for any close button that you create.

Leave a Reply

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

*

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