Transparency in uicontrols

I would like to welcome back guest blogger Robert Cumming, an independent UK contractor who developed a commercial class-based Matlab GUI framework. Today, Robert will highlight how he customized the use of uicontrol CData property.

Before detailing how I used this feature I will start with a basic example. A number of times (see example1, example2), users have asked is it possible to set the background of uicontrols to be transparent?

There are a number of reasons why we might want to do this. For example, we might wish to display a clickable image, and don’t want its background (which is typically white) to be displayed. To place on image on a uicontrol we use its CData property, which according to the official Matlab documentation must be a 3-D array of truecolor RGB values.

Let’s start with a simple example:

uicontrol with white bgcolor

uicontrol with white bgcolor

f = figure;
img = imread('Matlab_Logo.png');
s = size(img);
pb = uicontrol('Style','pushbutton', 'Position',[10 10 s(2) s(1)], 'CData',img, ...
               'Callback',@(a,b)disp('push button'), 'BackgroundColor','green');

The code above produces the figure on the right; when we click on the image, the pushbutton callback is executed.

However the background of the button is white. This is because the image is MxNx3 rectangle the size of the button.

We can set the white portion of the image to be transparent so that it will show the background color of the pushbutton (in our example, ‘green’).

First, we read the image and convert it to a 2D double array that ranges from 0 to 1 (the original image was RGB uint8, 0 to 255). Then find the index for each RGB where the value is 1 (white):

img = imread('Matlab_Logo.png');
img = double(img)/255;
index1 = img(:,:,1) == 1;
index2 = img(:,:,2) == 1;
index3 = img(:,:,3) == 1;
uicontrol with transparent bgcolor

uicontrol with transparent bgcolor

The color (in this example) that we want to make transparent is where all RGB is 1, so calculate a logical index where this is true and update the img variable:

indexWhite = index1+index2+index3==3;
for idx = 1 : 3
   rgb = img(:,:,idx);     % extract part of the image
   rgb(indexWhite) = NaN;  % set the white portion of the image to NaN
   img(:,:,idx) = rgb;     % substitute the update values
set(pb, 'CData', img)     % Update the CData variable

Updating the CData we get the image with the green background. We could set the Color of the figure to be green, to match the uicontrol’s background color:

set(f, 'Color', get(pb,'BackgroundColor'))

Transparent background

As mentioned here, we can link the CData to a screenshot image of the parent figure.

When we combine the two methods above, we get the effect of the uicontrol background being transparent (the smaller logo is a button that can be clicked):

uicontrol with transparent background (optical illusion)

uicontrol with transparent background (optical illusion)

f = figure(); % create a figure with an axes on it
ax = axes('Units','pixels', 'Position',[0 0 560 420], 'XTick',[], 'YTick',[], ...
          'Nextplot','add', 'YDir','reverse');
% read the big logo image - background of the figure
bigImage = imread('Matlab_LogoBig.png');
image(bigImage, 'parent', ax);  % Display the image in the axes
% read a smaller image - background of button
img = imread('Matlab_Logo.png');
s = size(img);
pos = [10 10 s(2) s(1)];  %Position of the button
% Extract the portion of the image where the button will be.
F = getframe(ax,pos);  % take a screenshot of the parent figure
pb = uicontrol('Style','pushbutton', 'Units','pixels', 'Position',pos, ...
               'Callback',@(a,b)disp('push button'));
% as before - calculate where the button image is white.
img = double(img)/255;
index1 = img(:,:,1) == 1;
index2 = img(:,:,2) == 1;
index3 = img(:,:,3) == 1;
indexWhite = index1+index2+index3==3;
% for each pixel, replace the white portion with the parent image data
for idx = 1 : 3
   rgb = 1-img(:,:,idx);                   % To make the picture quirky change the RGB
   pImage = double(F.cdata(:,:,idx))/255;  % extract part of the image
   rgb(indexWhite) = pImage(indexWhite);   % set the white portion of the image to the parent
   img(:,:,idx) = rgb;                     % substitute the update values
% Update the push button image
set(pb, 'CData', img)

Customizing checkboxes

I have shown how to manipulate the CData of a button. Unfortunately, not all uicontrols have a CData property — the documentation states that pushbuttons and toggle buttons are the only uicontrols that are fully supported. It also mentions that you can use it in radiobuttons and checkboxes, which brings me to how I used it in my application: I use this feature on a checkbox – to use it properly we need to ensure that the size of the image we put in CData is 16x16x3. In this case we set a transparent color by setting pixel RGB values to NaN:

uicontrol with transparent bgcolor

uicontrol with transparent bgcolor

f = figure('Color','red');
smiley = imread('smiley.png');
smiley = double(smiley)/255;
index1 = smiley(:,:,1) == 1;
index2 = smiley(:,:,2) == 1;
index3 = smiley(:,:,3) == 1;
indexWhite = index1+index2+index3==3;
% Create a first smiley which has the white background.
uicontrol('Style','checkbox', 'Position',[25 50 16, 16], 'CData',smiley, ...
          'Callback',@(a,b)disp('-1 smiley'));
% For each pixel, replace the white portion with the parent image data
for idx = 1 : 3
   rgb = smiley(:,:,idx);  % To make the picture quirky change the RGB
   rgb(indexWhite) = NaN;
   smiley(:,:,idx) = rgb;  % substitute the update values.
% Create a second smiley which has the transparent background.
uicontrol('Style','checkbox', 'Position',[25 25 16, 16], 'CData',smiley, ...
          'Callback',@(a,b)disp('+1 smiley'), 'BackgroundColor','red');

The upper smiley is the original image; the lower smiley has its white pixels set to NaN, and the background colors of the control and the figure set to equal. The checkbox has no text is displayed, the user just clicks on the smiley to invoke the callback.

Note: This trick works in R2014b but I have deliberately used old style set and get commands for compatibility with older versions of Matlab. I have used this in all versions from R2008a onwards, and I suspect it probably works in older versions as well.

I used this feature several times in my Matlab GUI Toolbox. One of the uses was to create a pin for locking a dynamic panel in position: The panel is by default hidden; when the user hovers the mouse near the edge, the dynamic panel appears after some predefined time (2 seconds). A checkbox with a manipulated CData masquerades as a pin for locking the panel in position. When the panel is pinned, the CData changes accordingly:

transparent uicontrol usage example
transparent uicontrol usage example


1. The CData property of a uicontrol can be set to NaN to imitate transparent behavior.
2. By linking this with the parent CData we can super-impose an image on top of another image.
3. We can customize other uicontrols using the method to turn checkboxes (for example) into clickable images.

Have you used this feature? If so please share in a comment below.

Editor’s note: I have shown another alternative for displaying clickable transparent images in my article on displaying animated/transparent GIFs. Readers might also find interest in the related article on transparent uipanels. Next week I plan to show how MathWorkers Ben Tordoff and David Sampson coerced a simple checkbox uicontrol to have a radically different appearance, as flex-panel dividers in their GUI Layout Toolbox, similarly to what Robert explained today. Stay tuned!  – Yair

Categories: Guest bloggers, GUI, Low risk of breaking in future versions, Undocumented feature

Tags: , , ,

Bookmark and SharePrint Print

5 Responses to Transparency in uicontrols

  1. Sergio says:

    It was a very well way to learn customize uicontrols.

    But I have a doubt. Is posible that a “CDATA image” can be placed in a left or right position of uicontrol object, not in the center position of uicontrol ?

    Thank you.

    Att: A Engineer.

  2. Jeff says:

    Hello Yair,
    I have used your exact code found in section “Transparent Background”, but the generated figure does not render the same as your example. There are vertical striations in the transparent button image. (Please see screenshot).

    I’m wondering if it is a software version issue. I’m running R2015b. Any ideas/solutions to repair this issue?
    Thank you.

  3. edouard says:

    Hello Yair! your codes are great!!! I used the transparent background one. It helped me a lot.

    I would add as a NB that the position “pos” used by the getframe function is set in the coordinate system of the axes graph, meaning the position of the child image and the position used in the getframe function should be seperated. Otherwise the getframe function take the background from another part of the image.

    I just have one question. When I superimpose the child image on the parent somewhere away from the edges I get a thin line colored by the ‘BackgroundColor’ on the left edge of the child image, meaning everything I want to be transparent is transparent except for that thin line. Do you have any idea what that could be due to? It seems to be something to do with the ‘Extent’ but I can’t figure it out..


Leave a Reply

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