- Undocumented Matlab - https://undocumentedmatlab.com -

Matlab layout managers: uicontainer and relatives

Posted By Yair Altman On June 9, 2010 | 25 Comments

When designing Matlab applications, we can either use Matlab’s designer (guide [1]), or manually position each GUI component programmatically, using its Position property. Matlab lacks the layout managers so common in Java, that enable easy relative component positioning, taking into account dynamic container size, components spacing weights etc. Of course, we can always trap the container’s ResizeFcn callback to update our layout, but doing so is one royal pain in the so-and-so…
Luckily, there is (of course) an undocumented solution to this problem, and at the public’s demand [2] I will detail it below. It doesn’t solve all layout-management needs, but it goes a long way. Most importantly, it uses pure Matlab – no Java knowledge whatsoever is needed.

uicontainer

Matlab’s uicontainer family (uicontainer, uiflowcontainer and uigridcontainer) consists of container objects that enable customizable layout management of contained components. Uicontainers can contain any Matlab component that may have a uipanel handle as a Parent property. This includes uicontrols, plot axes etc., as well as other uicontainers.
The basic uicontainer object appears to be little more than a transparent container for contained objects. It can be used interchangeably with uipanel, which appears to be a specialized type of a uicontainer. Indeed, as MathWorks notes [3]:
The UICONTAINER function is undocumented, and is not intended for direct use. The UIPANEL function should be used instead, as it provides more functionality.
In some cases, Matlab itself uses uicontainer instead of uipanel: for example, ActiveX controls are enclosed within transparent uicontrol objects when added to a figure:

>> [hActivex,hContainer] = actxcontrol('OWC11.Spreadsheet.11');
>> get(hContainer,'Type')
ans =
uicontainer

uicontainer objects are not very customizable. For example, unlike uipanels, uicontainers have no titles or borders. We would therefore usually prefer to use uipanels, as Mathworks suggested above. An exception to this rule is a case where we need to derive our own customized container class. An example of this is found in %matlabroot%/toolbox/matlab/uitools/@uitools/@uitab/schema.m, which derives uicontainer to create a uitab container (which will be described in a future article).
Relatives of uicontainer are more useful in general: uiflowcontainers and uigridcontainers act similarly to Java’s layout managers – specifically, FlowLayout [4] and GridLayout [5]. I expect to see additional layout managers incarnated within Matlab uicontainers in future Matlab versions (perhaps in the R2010b pre-release that came out today – I can’t wait to see…).

uiflowcontainer

uiflowcontainer is a uicontainer that enables adding uicontrols to the container without specifying an exact position as would be required for uicontainer or uipanel (actually, positions may be specified, but they are simply ignored).
By default, objects are added from the top-left corner, depending on the uiflowcontainer‘s available space and dimensions: if width > height then rightward, otherwise downward. If the container’s dimensions change, for example by resizing the figure window, then the container’s components will automatically be resized accordingly:

hc = uiflowcontainer('Units','norm','Position',[.1,.1,.8,.8]);
h1 = uicontrol('string','1','parent',hc);
h2 = uicontrol('string','2','parent',hc);
h3 = uicontrol('string','3','parent',hc);

'Auto' - before resizing figure
'Auto' - before resizing figure
…and after resizing
…and after resizing

The components flow direction within the container may be modified by setting the uiflowcontainer‘s FlowDirection property from its default value of ‘Auto’ to ‘AutoReverse’, ‘BottomUp’, ‘TopDown’, ‘LeftToRight’, or ‘RightToLeft’:

set(hc,'FlowDirection','BottomUp')
set(hc,'FlowDirection','RightToLeft')

'BottomUp'
'BottomUp'
'RightToLeft'
'RightToLeft'

Spacing between the components and the container’s border, and between themselves, may be controlled via the Margin property. By default, Margin is set to 2 (pixels):
Margin = 2 (default)
Margin = 2 (default)
Margin = 10
Margin = 10

The advantage of using uiflowcontainer is its automatic resizing and positioning of components. Notice how we simply specified the uiflowcontainer‘s handle as the control’s parent, and got all this functionality out-of-the-box!
If we need to use fixed-dimensions components, we can use uicontrol‘s undocumented properties HeightLimits and WidthLimits, each of which is a 2-element numeric vector specifying the minimal and maximal allowed value for the height or width (both of these vectors are [2,Inf] by default). uiflowcontainer tries to accommodate the requested limits by stretching or compressing its components (we need to resize the figure for the component resizing to become visible):

set(h1, 'HeightLimits',[10,20], 'WidthLimits',[30,30])
set(h2, 'HeightLimits',[50,50])
set(h3, 'HeightLimits',[2,inf])   % =default value

WidthLimits set
WidthLimits set

Sometimes, however, no amount of component resizing is enough to fully contain all components within the uiflowcontainer:

set(h2, 'WidthLimits',[150,150])
set(h3, 'HeightLimits',[50,50])  % resize figure to see effect

WidthLimits set
WidthLimits set

Note: uiflowcontainer normally ignores the specified limits if they would cause the component to stretch beyond the container boundaries. This happens unless the limits are identical (as in the preceding example), which informs uiflowcontainer that it has no judgment in the component’s dimensions.
In more complex cases, consider coding your own customized class deriving from uiflowcontainer. An example for such a customization can be seen in %matlabroot%/toolbox/matlab/uitools/@uitools/@uitabgroup/schema.m, which derives uiflowcontainer to create a uitabgroup container.
Components within a uiflowcontainer are ordered according to the order they were added to the container. This order can be modified by rearranging the handles in the container’s Children property, or by using the uistack function which does the same. Note that a side-effect of this is that the components dimensions are re-normalized:
uistack(h2,'top')
uistack(h2,'top')
uistack(h2,'bottom')
uistack(h2,'bottom')

uigridcontainer

uigridcontainer is similar to uiflowcontainer in its specialization of the layout: in this case, the container is divided into a transparent grid of N-by-M cells (1×1 by default), each of which can contain its own component:

hc = uigridcontainer('Units','norm','Position',[.1,.1,.8,.8]);
set(hc, 'GridSize',[2,3]);  % default GridSize is [1,1]
h1 = uicontrol('string','1','parent',hc);
h2 = uicontrol('string','2','parent',hc);
h3 = uicontrol('string','3','parent',hc);
h4 = axes('parent',hc); x = -4:.1:4; plot(h4,x,sin(x));
set(h4,'YTickLabel',[],'XTickLabel',[]);

A 2-by-3 uigridcontainer
A 2-by-3 uigridcontainer

The grid cells relative size can be controlled via the HorizontalWeight and VerticalWeight properties (set to NaN by default). These properties should be a numeric vector the same size as the corresponding number of cells. The property values are not important – only their relative values are used to control the relative cell dimensions. The EliminateEmptySpace property (default=’off’) controls whether empty grid rows/columns are eliminated from the container or displayed. As in uiflowcontainers, the Margin property controls the spacing between the internal components and borders:

set(hc, 'HorizontalWeight',[6,3,1], 'VerticalWeight',[0.2,0.5])
delete([h2,h3]);  % only h1,h4 remain
set(hc,'EliminateEmptySpace','on')

Non-equal grid weights
Non-equal grid weights
EliminateEmptySpace='on'
EliminateEmptySpace='on'
...and 'off'
...and 'off'

Other layout alternatives

Brad Phelan of XTargets has created [6] Matlab equivalents of Java’s BorderLayout [7] and SpringLayout [8]. The advantage of using Brad’s layout managers is that they appear to have full Matlab interoperability, including the ability to add Matlab components, unlike Java’s layout managers.
A File Exchange contributor named Jason has added a GridBagLayout implementation [9], mimicking Java’s well-known GridBagLayout [10].
Additional and more flexible layout managers are available in Java (one of my favorites is JGoodies Forms [11], which is pre-bundled with Matlab). Just remember the limitation that no Matlab component (such as GUI controls or plot axes) can be added to Java containers. Therefore, feel free to use these Java containers as long as their contained GUI is limited to Java components (JButton, JComboBox etc.).

Other uitools

Today’s article about uicontainer and its relatives was the first of several posts that will describe undocumented functions that reside in the %matlabroot%/toolbox/matlab/uitools folder. Feel free to look within this folder for other interesting undocumented functions. Most of these functions are semi-documented, meaning that they have a usable help-section hidden within the m-file (type “edit uicontainer.m” for example). Many have existed more-or-less unchanged for many releases. Note that there is no guarantee that they will remain in future releases. When using unsupported functionality, always code defensively.

Categories: GUI, Handle graphics, Low risk of breaking in future versions, Semi-documented function


25 Comments (Open | Close)

25 Comments To "Matlab layout managers: uicontainer and relatives"

#1 Comment By per isakson On June 10, 2010 @ 09:33

Thank you Yair for this blog and this post. I really appreciate the insight.

You don’t mention the [18] that appeared on the File Exchange last month. It seems to share ancestors with Brad Phelan’s layout managers. Brad, who once worked for The Mathworks, is acknowledged.

GUI Layout Toolbox
by Ben Tordoff
(The Mathworks)

/ per

#2 Comment By Yair Altman On June 11, 2010 @ 08:34

@per – my bad for the oversight – thanks for pointing it out. The GUI Layout Toolbox is indeed an excellent utility. Funny it was published only two weeks ago and I missed it…

#3 Comment By Chaitanya On June 22, 2010 @ 19:32

Hi Sir,
I am a beginner in Matlab. I have saved data from the workspace into a mat file. It consists of vectors of sizes 82×3 , 32×1 … Now I intend to print it out in the form of a table. Should I convert it to excel? How should I create tables from workspace data(in the form of mat files)? Awaiting your reply.

#4 Comment By Yair Altman On June 23, 2010 @ 00:37

@Chaitanya – you can use the [19] function to display and print data in table format in Matlab. uitable was undocumented (but available) until R2008a.

Alternately, you can display your data in the Variable (Array) Editor, using the [20] function:

data=magic(4); openvar('data');

#5 Pingback By Tabbed panes – uitab and relatives | Undocumented Matlab On June 23, 2010 @ 11:45

[…] 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 […]

#6 Comment By Simon On July 9, 2010 @ 06:48

Yair, thank you for your blog. It’s very useful!

When did the Height/WidthLimits property appeared? It doesn’t seem to work in R2007b. What I get is:

??? Error using ==> set
There is no 'HeightLimits ' property in the 'uicontrol' class.

Thank you
Sim

#7 Comment By Simon On July 9, 2010 @ 08:22

Never mind, I just noticed that the container needed to be a uiflowcontainer. uigridcontainer does not enable the ‘HeightLimits‘ hidden property.

Sim

#8 Comment By Simon On July 9, 2010 @ 08:27

Well, disregard again, the error disappeared because I commented my line of code. So I still have the problem. Anyways, here’s what uiflowcontainer.m tells about these hidden properties

% properties only visible when parent is uiflowcontainer
%set([c1,c2],'HeightLimits',[20 20],'WidthLimits',[60 60])

Which is what I’m doing, but without success with R2007b.

#9 Comment By Yair Altman On July 11, 2010 @ 10:15

@Simon – I’m not sure why it’s not working for you. It does work fine on my Matlab R2007b on a Windows XP platform:

hc = uiflowcontainer;
hb = uicontrol(...,'Parent',hc);
get(hb,'HeightLimits');

From your quoted error message above, I see that you called the property ‘HeightLimits ‘ (with an extra space) – perhaps this is the problem?

#10 Comment By Simon On July 12, 2010 @ 09:09

My error was to set the HeightLimits property at uicontrol creation, instead of using a separate set(‘HeightLimits’).

Thanks!
Simon

#11 Comment By Kesh On August 18, 2010 @ 07:01

A little heads-up for using the uiflowcontainer object.

When the container is copied using copyobj, the WidthLimits and HeightLimits properties of its children are not copied.

And MathWorks, why oh why do you not have these limits properties implemented for uigridcontainer children??? I hope they have it on the to-do list…

#12 Comment By sebbo On January 8, 2013 @ 02:23

Hi,

these containers are great.
One issue I’m having though is that patch objects (as e.g. used by a bar-plot) seem to have problems, when drawn in an axes which has a flow/gridcontainer as parent.
After zooming the axis, the patch-graphics which is not in the zoomed axis-range any more keeps being drawn outside the axis-area.
Surface-plots on the other hand seem to be ok…

This is in R2011b.
Has anybody else come across this problem?
It would be great if there’s a workaround…

ps:
Here’s a minimalistic example demonstrating the problem:

% create figure with 1 x 2 gridcontainer, holding 2 empty panels:
f = figure();
grid = uigridcontainer(f, 'gridsize', [1,2]);
p1 = uipanel(grid);
p2 = uipanel(grid);
    
% construct axis in 2nd panel
axes('parent', p2);

% draw a trivial line as patch-object
patch(1:10, 1:10, 'green', 'EdgeColor', 'green');

% modify axis-range
xlim([2,8]);

#13 Comment By Benjamin Charlton On November 6, 2013 @ 14:27

Hello, quick question on uipanels/button groups, how can i make one item (a radio button) with in the uipanel visible/not visible…
the code “set(handles.uibatspanel,’visible’,’off’)” makes the panel itself visible or not, but i want the radio button “raido2bats” within this panel to be visiable/not visiable

Many Thanks

Ben

#14 Comment By Yair Altman On November 6, 2013 @ 14:47

set(handles.radio2bats,'Visible','off')

#15 Comment By Yaroslav On June 11, 2014 @ 06:42

Hi @Yair,

Thank you for the enlightening article; I find these functions extremely useful (just the freedom of not using the 'Position' property in each control saves me a huge load of time and effort). However I find them lacking in one tiny aspect:

What I need is something like a uiflowpanel function; i.e., having the uiflowcontainer with the uipanel‘s frame and title — all in one handle-graphics object. To be more precise, I want an object, such that if I set(...) a property or use inspect(...) it, I would see all the properties of the uipanel and the uiflowcontainer together (same request extends naturally for uigridcontainer).

Currently I use a nested object scheme:

function [fch,pnh] = uiflowpanel(varargin)
% UIPANELCONTAINER Mimicking UIPanel w/ UIFlowContainer capabilities
pnh  = uipanel(varargin{:});
fch  = uiflowcontainer('Parent',pnh,'Units','normalized','Position',[0 0 1 1], ...
    'FlowDirection','topdown','Background',get(pnh,'Background'));
end

but I wish for a more robust solution. I thought of combining two UDD classes (via inheritance or any other method), but I am not quite sure how to do it. Can you help?

Kind regards,
Yaroslav

#16 Comment By Yair Altman On June 11, 2014 @ 06:53

@Yaroslav – take a look at my [21] and how it adds properties to existing UDD handles via the [22] function.

Note that unfortunately this feature is no longer available in the [23].

For more information on UDD inheritance, [24].

#17 Comment By Yaroslav On June 11, 2014 @ 09:13

The problem with adding properties to existing UDD handles, is that one must redefine all the new properties; I want to merge two UDD classes (double inheritance, etc.). Is it possible?

#18 Comment By Yair Altman On June 11, 2014 @ 09:25

I am not aware of the ability to inherit multiple UDD superclasses, but this is not the same as saying that it’s not possible. Perhaps Donn Shull knows how to do it. I’d start looking in Donn’s article on UDD inheritance.

In uicomponent I wanted to merge the properties of the Java object and the Matlab container. So I took one of them and simply added to it (dynamically, using schema.prop) the properties of the other. Whenever I added such a dynamic property, I also overrode the new property’s set method and added handle.listeners, so that the original and the new properties would be linked, such that modifying any of them in run-time would automatically update the other. All this is done in a loop over the properties, so it is quite efficient and generic. Look at the source code of uicomponent for details – it’s well documented.

#19 Pingback By how to mislay a impression with jquery – Accardo On September 8, 2014 @ 19:05

[…] exact, MATLAB has some undocumented plans managers: uiflowcontainer and uigridcontainer. See this article by Yair […]

#20 Pingback By Is there something peculiar to Matlab or Mathworks that supports so much “undocumented” code? | DL-UAT On June 16, 2015 @ 16:36

[…] while researching UI layout techniques for programmatic GUI creation one of their articles made mention of this uiflowcontainer, which if you get the documentation on it you find it is undocumented. […]

#21 Comment By Shalin On January 15, 2016 @ 18:41

Is there a way to specify a minimum height or width of uigridcontainer?

#22 Comment By Yair Altman On January 16, 2016 @ 19:21

You can use the GridSize and Position properties (default values = [1,1] and [0,0,1,1] meaning 100% in both directions, when Units='normalized')

#23 Comment By nirvana-msu On April 29, 2016 @ 20:08

Hi Yair,

Isn’t this statement incorrect?

Just remember the limitation that no Matlab component (such as GUI controls or plot axes) can be added to Java containers.

You cannot add axes, but you can manage a mixture of java components and uicontrols using swing layout mangers. You just need to add the corresponding java handles of uicontrol objects to your java container.

E.g. here’s an example applying a BoxLayout with a horizontal glue to a couple of uicontrol buttons:

parent = figure();
jPanel = javaObjectEDT('javax.swing.JPanel');

jPanel.setLayout(javax.swing.BoxLayout(jPanel,javax.swing.BoxLayout.X_AXIS));

hButton = uicontrol('String', 'Button 1');
jButton = findjobj(hButton);
jPanel.add(jButton);

jPanel.add(javax.swing.Box.createHorizontalGlue());

hButton2 = uicontrol('String', 'Button 2');
jButton2 = findjobj(hButton2);
jPanel.add(jButton2(1));

parentPixelPos = getpixelposition(parent);
[~, hContainer] = javacomponent(jPanel, [1, 1, parentPixelPos(3), parentPixelPos(4)], parent);
set(hContainer, 'Units', 'normalized');

I don’t really see much point using uiflowcontainer and alike. GUI Layout toolbox is perfect for most of the tasks, and when you need a fine-grained control of uicontrol, layout you can use the technique above (mixing them with java components if required).

#24 Comment By Yair Altman On April 30, 2016 @ 20:37

@nirvana – this is correct, but what you are essentially doing is adding a Java component to a Java container – you are not adding the Matlab uicontrol. In this respect, using the underlying Java peer (via findjobj) is bypassing this limitation. Unfortunately, axes do not have similar Java peers that can be manipulated in a similar manner – they do have a Java canvas that can be accessed, but it extends over the entire figure’s ContentPane (in theory you could try to resize that canvas and add it to the JContainer, but odd things might result…).

#25 Comment By nirvana-msu On April 30, 2016 @ 23:17

True, we add java peers and not uicontrol handles themselves, but at the end of the day it does allow us to effectively manage the layout of arbitrary uicontrols (and java components) using flexible Java layout managers, which, I think, not a lot of people realize.
Btw, thanks for all your great utilities and tips : )


Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/matlab-layout-managers-uicontainer-and-relatives

URLs in this post:

[1] guide: http://undocumentedmatlab.com/blog/guide-customization/

[2] the public’s demand: https://www.mathworks.com/matlabcentral/newsreader/view_thread/279442#736318

[3] notes: http://www.mathworks.com/support/solutions/en/data/1-OQBBH/

[4] FlowLayout: http://java.sun.com/docs/books/tutorial/uiswing/layout/flow.html

[5] GridLayout: http://java.sun.com/docs/books/tutorial/uiswing/layout/grid.html

[6] created: http://web.archive.org/web/20071015004151/http://xtargets.com/cms/Tutorials/Matlab-Programming/Advanced-Layout-Management-With-Handle-Graphics.html

[7] BorderLayout: http://java.sun.com/docs/books/tutorial/uiswing/layout/border.html

[8] SpringLayout: http://java.sun.com/docs/books/tutorial/uiswing/layout/spring.html

[9] GridBagLayout implementation: http://www.mathworks.com/matlabcentral/fileexchange/22968

[10] GridBagLayout: http://java.sun.com/docs/books/tutorial/uiswing/layout/gridbag.html

[11] JGoodies Forms: http://www.jgoodies.com/freeware/forms/

[12] Tab panels – uitab and relatives : https://undocumentedmatlab.com/articles/tab-panels-uitab-and-relatives

[13] Setting the Matlab desktop layout programmatically : https://undocumentedmatlab.com/articles/setting-the-matlab-desktop-layout-programmatically

[14] Listbox layout customization : https://undocumentedmatlab.com/articles/listbox-layout-customization

[15] Common javacomponent problems : https://undocumentedmatlab.com/articles/common-javacomponent-problems

[16] FindJObj – find a Matlab component's underlying Java object : https://undocumentedmatlab.com/articles/findjobj-find-underlying-java-object

[17] Images in Matlab uicontrols & labels : https://undocumentedmatlab.com/articles/images-in-matlab-uicontrols-and-labels

[18] : http://www.mathworks.com/matlabcentral/fileexchange/27758-gui-layout-toolbox

[19] : http://www.mathworks.com/access/helpdesk/help/techdoc/ref/uitable.html

[20] : http://www.mathworks.com/access/helpdesk/help/techdoc/ref/openvar.html

[21] : http://www.mathworks.com/matlabcentral/fileexchange/14583-uicomponent-expands-uicontrol-to-all-java-classes

[22] : https://undocumentedmatlab.com/blog/udd-properties

[23] : https://undocumentedmatlab.com/blog/hg2-update

[24] : https://undocumentedmatlab.com/blog/hierarchical-systems-with-udd

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.