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
Categories: GUI, Handle graphics, Hidden property, Low risk of breaking in future versions, Stock Matlab function, UI controls

Tags: , , , , , ,

Bookmark and SharePrint Print

15 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?

    • 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?

    • 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

  4. Ninad kubal says:

    Can i add callback on any property change of matlab uipanel or uicontrol?

  5. Patrick Holland says:

    Hello Mr. Altman,
    I don’t know where exactly to ask, so I ask here.
    I found in the internet one respond from you

    [jPanel,hPanel] = javacomponent(javax.swing.JPanel);
    set(hPanel, 'units','normalized','position',[.1,.1,.8,.8]);
    hControl = uicontrol('style','pushbutton', 'parent',hPanel, 'string','click me');

    I have tried this code with Matlab 2013b and the Panel is empty somehow. I don’t know why.
    But my question IS… I want to add an undetermined amount of editboxes and labels to a panel. It can be 1 or 32 or even more.
    I don’t want to resize them according to the space because then they would be extremely too small. So i need a Scrollbar.

    I thought to use a JPanel and put it in a JScrollpane, but i failed at the first step up there. The jPanel is empty.
    Do you know what’s wrong?

    greetings

  6. Kusi says:

    In R2014b, it seems like the TitleHandle property is gone. Is there another way to have panel-level check boxes?

    • @Kusi – no: in HG2 (R2014b) the Matlab uipanel is (finally!) implemented as a true Java Swing component (deriving from JPanel), and the title is implemented as a standard Java titled-border. In other words, it is no longer a separate uicontrol.

      Instead, you can simply place a dedicated checkbox uicontrol on top of the panel, you just need to ensure the position is correct and normalized so that it moves with the panel when it changes its size/position.

Leave a Reply


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