File Exchange

image thumbnail

UISplitPane - Split a container (figure/frame/uipan​el) into two resizable sub-containers

version 1.4 (68.9 KB) by

Split a container (figure/frame/uipanel) into two resizable sub-containers, like Java's JSplitPane

9 Downloads

Updated

View License

Editor's Note: This file was selected as MATLAB Central Pick of the Week

Syntax:
[h1,h2,hDivider] = uisplitpane(hParent,'propName',propVal,...)
 
Description:
UISPLITPANE splits the specified container(s) (figure, panel or frame, referenced by handle(s) hParent) into two distinct panes (panels) separated by a movable divider. If no hParent container is specified, then the current figure (gcf) is assumed. Matlab components may freely be added to each of the panes. Pane sizes may be modified by dragging or programmatically repositioning the movable divider.
UISPLITPANE returns the handles to the left/bottom sub-container h1, right/top sub-container h2, and the split-pane divider hDivider. If a vector of several hParents was specified, then h1,h2 & hDivider will be corresponding vectors in the containing hParents. If the hParents are found to be non-unique, then the returned handles will correspond to the unique sorted vector of hParents, so that no hParent will be split more than once.
 
The UISPLITPANE divider can be dragged to either side, up to the specified DividerMinLocation to DividerMaxLocation property values (defaults: 0.1 and 0.9 respectively, meaning between 10-90% of range). In Matlab 7+, additional one-click buttons are added to the divider, which enable easy flushing of the divider to either side, regardless of DividerMinLocation & DividerMaxLocation property values.
 
Several case-insensitive properties may be specified as P-V pairs:
 - 'Orientation': 'horizontal' (default) or 'vertical'
 - 'Parent': Handle(s) of containing figure/panel/frame
 - 'DividerWidth': Divider width (1-25 [pixels], default=5)
 - 'DividerColor': Divider color (default=figure background color)
 - 'DividerLocation': Divider normalized initial location (.001-.999, default=0.5)
 - 'DividerMinLocation': Normalized minimal left/bottom pane size (0-1, default=0.1)
 - 'DividerMaxLocation': Normalized maximal left/bottom pane size (0-1, default=0.9)
 
hDivider is a standard Matlab object handle possessing all these additional properties. All these properties are gettable/settable via the hDivider handle, except for the 'Orientation' & 'Parent' properties which become read-only after the UISPLITPANE is constructed. hDivider also exposes the following read-only properties:
 - 'LeftOrBottomPaneHandle': h1 value returned by this function
 - 'RightOrTopPaneHandle': h2 value returned by this function
 - 'DividerHandle': the HG container handle (a numeric value)
 - 'JavaComponent': handle to the underlying java divider obj
 - 'ContainerParentHandle': handle to hParent container
                    Note: this is important in Matlab 6 which does
                    ^^^^ not allow hierarchical UI containers
 - 'ContainerParentVarName': hParent variable name if available
 
Example:
[hDown,hUp,hDiv1]=uisplitpane(gcf,'Orientation','ver','dividercolor',[0,1,0]);
[hLeft,hRight,hDiv2]=uisplitpane(hDown,'dividercolor','r','dividerwidth',3);
t=0:.1:10;
hax1=axes('Parent',hUp); plot(t,sin(t));
hax2=axes('parent',hLeft); plot(t,cos(t));
hax3=axes('parent',hRight); plot(t,tan(t));
hDiv1.DividerLocation = 0.75; % one way to modify divider...
set(hDiv2,'DividerColor','red'); % ...and this is another way...
 
Technical description:
http://UndocumentedMatlab.com/blog/uisplitpane

Bugs and suggestions:
Please send to Yair Altman (altmany at gmail dot com)
 
Warning:
This code heavily relies on undocumented and unsupported Matlab functionality. It works on Matlab 6+, but use at your own risk!

Comments and Ratings (23)

Meade

Meade (view profile)

@Yaroslav has reconciled the error. It comes from calling the mouse position from inside a uipanel, not from the figure directly.

Food for thought.

Thanks again for the excellent function!

Meade

Meade (view profile)

Just a fantastic bit of functionality that should be rolled into a full release by MW.

I'm having an issue with sizing of the uipanes and how any child axes react. This is a cross post with 'Cursorbar' which you covered on your blog.

For example, look how each cursor reacts differently based on the pane its in.
Any thoughts? (I have also posted to @Yaroslav to see if he can reconcile.)

<code>
figure();

[hDown,hUp,hDiv1] = uisplitpane(gcf,'Orientation','ver','dividercolor',[0,1,0]);
[hLeft,hRight,hDiv2] = uisplitpane(hDown,'dividercolor','r','dividerwidth',3);
t=0:.1:10;
hax1=axes('Parent',hUp); p1 = plot(t,sin(t));
hax2=axes('parent',hLeft); p2 = plot(t,cos(t));
hax3=axes('parent',hRight); p3 = plot(t,tan(t));

hCB1 = Cursorbar(p1);
hCB2 = Cursorbar(p2);
hCB3 = Cursorbar(p3);
</code>

Adam

Adam (view profile)

Does not work for me with R2014a.

The divider does not appear correctly, the panes aren't resizable.
I got the following exception during the example run.

Attempt to reference field of non-structure array.

Error in uisplitpane>dividerPropChangedCallback (line 712)
                jDivider.repaint;

Error in split (line 9)
set(hDiv2,'DividerColor','red'); % ...and this is another way...

Great work, I hope it will work for me, too.

Yair Altman

Yair Altman (view profile)

@Karl/Thierry - the latest version supports R2014b. Note that numerous modifications were required for R2014b and all this while keeping backward-compatibility with earlier Matlab releases. So it is quite possible that there are still a few problems. But as far as I can see it works well now.

Karl

Karl (view profile)

Very nice submission. I would give it 6 stars if it worked in R2014b.

Karl

Karl (view profile)

Does not work currently with R2014b / HG2.

SSOI SS

I can also reproduce the error described by Martin in 2011b release. Right click on splitter produces heavy red java errors in workspace

Pirmin Borer

A cool feature would be a dock, undock button....
However, Nice job!!

Joseph Burgel

Very cool Yair. Once again, job well done. You should be getting a check from MW.

Zach

Zach (view profile)

One question I have though, I'm not able to get a uitree to resize when placed in one of the panes this creates:

fig_handle = figure;
[tree_pane,split_pane,hDiv] = uisplitpane(fig_handle,'Orientation','horizontal','DividerLocation',0.3,'DividerColor',[0.6 0.6 0.6]);
[top_pane,bottom_pane,vDiv] = uisplitpane(split_pane,'Orientation','vertical','DividerLocation',0.5,'DividerColor',[0.6 0.6 0.6]);

root_node = uitreenode('Test','Test', [], 0);
Tree = uitree('v0','Parent',tree_pane,'Root',root_node);
set(Tree,'Units',get(tree_pane,'Units'));
size_pane = get(tree_pane,'Position');
set(Tree,'Position',[0 0 size_pane(3) size_pane(4)]);

The uitree is sized correctly initially, and seems to resize in the vertical direction when the figure is resized, but when the sliders are moved, the uitree doesn't change. Anything that can be done about this?

Zach

Zach (view profile)

Yair Altman

Yair Altman (view profile)

@Martin - thanks for pointing this out. It is only a problem when right-clicking the divider, so as long you left-click/drag you're safe.

The right-clicking problem also occurs on earlier Matlab versions, and is due to some very internal Matlab-Java integration reason. (If you must know, because the divider's javacomponent-created HGPanel is a heavyweight AWT Component instead of a lightweight Swing JComponent). I am unable to bypass this problem at the moment. If I find a way I'll post an updated function here.

Martin

Martin (view profile)

Hello, I found the following JAVA exception if the divider is dregged using the right mouse button after button release:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: com.mathworks.hg.peer.HGPanel cannot be cast to javax.swing.JComponent
at javax.swing.plaf.basic.BasicLookAndFeel$AWTEventHelper.eventDispatched(Unknown Source)
at java.awt.Toolkit$SelectiveAWTEventListener.eventDispatched(Unknown Source)
at java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Unknown Source)
at java.awt.Toolkit$ToolkitEventMulticaster.eventDispatched(Unknown Source)
at java.awt.Toolkit.notifyAWTEventListeners(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

I use R2008b.
Martin

Martin

Martin (view profile)

Sorry, it is in R2008b ...

Hans

Hans (view profile)

Very useful. Thanks, Yair.

Co Melissant

A brilliant piece of work, very useful. Especially since the user do not need any java skills if she/he does not like to.

S B

S B (view profile)

Thank You. Works perfect

Jveer

Jveer (view profile)

yes yes i apologise i missed it.

well i found a bug or maybe i'm just using it wrong. emailing to you now.

Yair Altman

Yair Altman (view profile)

@Jveer - you can customize the divider using the 'DividerWidth' and 'DividerColor' properties. By default, a standard width of 5 pixels and the figure's background color are used. I used fat and colored dividers in the screenshot for demonstration purposes only, but you can set them to whatever you need. Read the help section for other settable properties.

Jveer

Jveer (view profile)

wow! that i just brilliant!! thank you!

a very minor recommendation - any chance of changing those fat and ugly colored lines into something more discrete and professional looking?

Yair Altman

Yair Altman (view profile)

Hi Sivakumar,

uisplitpane returns 3 handles: 2 handles of the uipanels on either side of the divider, and the divider handle. You can add both JTabbedPane and uitabgroup to either of the uipanels, as follows (at least on R2007b):

[hPanel1,hPanel2,hDivider] = uisplitpane(...);

hTabs = uitabgroup('parent',hPanel1);
t1 = uitab(hTabs, 'title', 'Panel 1');
a = axes('parent', t1); surf(peaks);
t2 = uitab(hTabs, 'title', 'Panel 2');
closeb = uicontrol(t2, 'String', 'Close Me', ...
'Position', [180 200 200 60], 'Call', 'close(gcbf)');

h3=javacomponent('javax.swing.JTabbedPane',[20,20,100,200],hPanel2);

Yair

S B

S B (view profile)

Do you know how do I embed either a jtabbedpane or uitab in the sub-container so that I can move the dividers and the tab group also moves accordingly. I tried with uitabgroup but it was not accepting the "parent" as one of your sub-component.

Updates

1.4

Fixes for HG2 (R2014b); improved mouse-movement performance (responsivity)

1.3

Fixed some HG-Java warnings; fixed the panels' default bgcolor to be the same as their parent's bgcolor; fixed divider's arrow buttons bgcolor; fixed divider size upon dragging (panel resize); fixed minor Java issues with the divider sub-component

1.2

Fixed DividerColor parent's color based on Co Melissant's suggestion; re-fixed JavaFrame warning

1.1

Fix for R2008b JavaFrame warning

MATLAB Release
MATLAB 6.0 (R12)

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video