Panel-level uicontrols

In one of my larger Matlab applications – Integration-lab Debriefing System (IDS, which shall be described in a future dedicated article) – I wanted to present a panel-level checkbox that applies to the entire panel contents. In my particular case, the IDS uipanel contained a Java table (another future topic) with multiple selectable rows, and I needed a global checkbox that selects all (or none) of them at once:

Panel-level ("Objects") checkbox

Panel-level ("Objects") checkbox

One way to do this is to calculate the checkbox’s desired position relative to the uipanel and place a regular checkbox-style uicontrol there. The checkbox can even be made a child of the uipanel with ‘normalized’ units, thereby moving and resizing it together with its uipanel parent when the later is moved or resized.

But there’s a much simpler method that want to share. It relies on the undocumented fact that the uipanel‘s title label is a simple hidden uicontrol child of the uipanel handle. This uicontrol handle can be found and simply transformed from a ‘style’='text’ control into a ‘style’='checkbox’ control, as follows:

% Prepare the panel
hPanel = uipanel('position',[0.2,0.2,0.4,0.4], 'title','Objects');
 
% Get the title label's handle
warning off MATLAB:Uipanel:HiddenImplementation  % turn off warning
hTitle = setdiff(findall(hPanel),hPanel);  % retrieve title handle
hTitle = get(hPanel,'TitleHandle');  % alternative, uses hidden prop
 
% Modify the uicontrol style; add 20 pixel space for the checkbox
newPos = get(hTitle,'position') + [0,0,20,0];  % in pixels
set(hTitle, 'style','checkbox', 'value',1, 'pos',newPos);

Panel-level checkbox

Panel-level checkbox

Note that we can retrieve the title handle using either the uipanel‘s hidden property TitleHandle, or by scanning the panel’s children using findall. I prefer the TitleHandle approach because it does not require modification (minor as it might be) when the panel already contains other children.

The down-side is that since TitleHandle is an undocumented hidden property, it may change its name, its behavior or even be removed in some future Matlab release. In fact, there’s even a Matlab warning about this, unless you turn it off using:

warning off MATLAB:Uipanel:HiddenImplementation

We can use this approach for more complex options panels, as the following example illustrates. Here, we set radio-button controls rather than a checkbox control, and also modify the title color to blue:

% Main panel and basic alternative control
hPanelMain = uipanel('pos',[.1,.1,.8,.8], 'Title','Main', 'units','norm');
hAlt1 = uicontrol('parent',hPanelMain, 'units','norm', 'pos',[.1,.8,.5,.1], 'style','radio', 'string','Alternative #1');
 
% Alternative options panel #2
hAlt2 = uipanel('parent',hPanelMain, 'units','norm', 'pos',[.07,.4,.5,.35], 'title','Alternative #2');
hAlt2Title = get(hAlt2, 'TitleHandle');
newPos = get(hAlt2Title,'position') + [0,0,20,0];  % in pixels
set(hAlt2Title, 'style','radio', 'pos',newPos);
hAlt2a = uicontrol('parent',hAlt2, 'units','norm', 'pos',[.2,.6,.7,.3], 'style','checkbox', 'string','Option 1');
hAlt2b = uicontrol('parent',hAlt2, 'units','norm', 'pos',[.2,.2,.7,.3], 'style','checkbox', 'string','Option 2');
 
% Alternative options panel #3
hAlt3 = uipanel('parent',hPanelMain, 'units','norm', 'pos',[.07,.05,.5,.3], 'title','Alternative #3');
hAlt3Title = get(hAlt3, 'TitleHandle');
newPos = get(hAlt3Title,'position') + [0,0,20,0];  % in pixels
set(hAlt3Title, 'style','radio', 'pos',newPos, 'ForegroundColor','blue');
hAlt3a = uicontrol('parent',hAlt3, 'units','norm', 'pos',[.2,.5,.7,.3], 'style','popup', 'string',{'Option 3a','Option 3b','Option 3c'});

Advanced panel-level controls

Advanced panel-level controls

Note that since the hAlt2Title and hAlt3Title radio-buttons are children of their respective uipanel parents, we cannot use a simple uibuttongroup to group them in a mutual-exclusion group. Instead, we must use a dedicated callback function. This is actually quite easy:

% Set the callback for all relevant radio-buttons
hButtonGroup = [hAlt1, hAlt2Title, hAlt3Title];
set(hButtonGroup, 'Callback', {@SelectionCb, hButtonGroup});
 
% This is the callback function that manages mutual exclusion
function SelectionCb(hSrc,hEvent,hButtonGroup)
   otherButtons = setdiff(hButtonGroup,hSrc);
   set(otherButtons,'value',0);
   set(hSrc,'value',1);  % needed to prevent de-selection
end

Related posts:

  1. Images in Matlab uicontrols & labels Images can be added to Matlab controls and labels in a variety of manners, documented and undocumented. ...
  2. GUI integrated HTML panel Simple HTML can be presented in a Java component integrated in Matlab GUI, without requiring the heavy browser control....
  3. GUI integrated browser control A fully-capable browser component is included in Matlab and can easily be incorporated in regular Matlab GUI applications. This article shows how....
  4. Bug and workaround in timeseries plot Matlab's internal hgconvertunits function has a bug that affects timeseries plots. Luckily there is a simple workaround....
  5. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  6. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...

Categories: GUI, Handle graphics, Hidden property, Low risk of breaking in future versions, Stock Matlab function, UI controls

Tags: , , , , , ,

Bookmark and Share Print Print

7 Responses to Panel-level uicontrols

  1. Alex says:

    In the first image in this article, how did you achieve the horizontal line under the tabs that are not active?

    • Yair Altman says:

      Alex – The uitab control (explained here, with additional articles earlier this month that showed how to customize the tab appearance and behavior), hides the separator line in its internal implementation. In the example on this page I used a Java JTabbedPane directly, and this preserves the separator line. Here’s a simple example:

      [jTabbedPane, hContainer] = javacomponent('javax.swing.JTabbedPane', [20,50,200,200], gcf);
      jTabbedPane.addTab('tab #1',javax.swing.JPanel);
      jTabbedPane.addTab('tab #2',javax.swing.JPanel);
    • Alex says:

      Thanks, that’s exactly what I was looking for. Can you give ma an example how to add a Matlab uicontrol and axes to a tab? Can I set the ‘parent’ property to an uicontrol or is there another way now?

    • Yair Altman says:

      Alex – Matlab uicontrols and axes cannot be added to Java containers (well, at least not without a herculean effort).

      This is why MathWorks implemented uitab so that uicontrols/axes are not added directly to the tabs but rather to invisible Matlab containers that are handled by the tab callbacks.

      Under the hood, uitab is a simple JTabbedPane that has no containers, only tabs. So, fixing it such that the missing separator line appears should be a simple enough exercise for you.

      Please post the necessary changes to the uitab.m file (or its relatives) here if and when you succeed.

    • Alex says:

      Is it in the schema.m? I tried to modify the line

      jpanel = javax.swing.JPanel(java.awt.BorderLayout);
      [comp2, h.HgContainer] = javacomponent(jpanel,[1 1 1 1], h.parent);

      but I couldn’t see the effect.
      I’m new to Java, so could you please give me more hints?

  2. Alex says:

    I looked at jTabGroup using

    uiinspect(jTabGroup)

    is there a property to make the separator line appear?

  3. Pingback: Using Java 7 in Matlab R2013a and earlier | 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>