Help with GUI Layout toolbox
12 views (last 30 days)
Show older comments
Sankar Mahadevan
on 4 Mar 2018
Edited: Mohammad Askari
on 13 Apr 2022
Hello,
I am trying to add a legend to the dockexample as shown below (from the GUI layout toolbox). But when I do this, the plot gets erased and I can only see the legend notations on the axes. How do I plot and add a legend.
I believe since the parent of the axes is the panel, the legend is not a child of the axes.
Not sure how to fix this.
Please see the code below
function dockexample()
%DOCKEXAMPLE: An example of using the panelbox dock/undock functionality
% Copyright 2009-2013 The MathWorks Ltd.
% Create the window and main layout
fig = figure()
box = uix.HBox( 'Parent', fig );
uicontrol( 'Style', 'listbox', 'Parent', box, 'String', {'Item 1','Item 2'} );
% Add three panels to the box
panel{1} = uix.BoxPanel( 'Title', 'Panel 1', 'Parent', box );
panel{2} = uix.BoxPanel( 'Title', 'Panel 2', 'Parent', box );
panel{3} = uix.BoxPanel( 'Title', 'Panel 3', 'Parent', box );
% Add some contents
uicontrol( 'Style', 'PushButton', 'String', 'Button 1', 'Parent', panel{1} );
uicontrol( 'Style', 'PushButton', 'String', 'Button 2', 'Parent', panel{2} );
box1 = uix.VBox( 'Parent', panel{3} );
box2 = uix.HBox( 'Parent', box1 );
uicontrol( 'Style', 'PushButton', 'String', 'Button 3', 'Parent', box1 );
uicontrol( 'Style', 'PushButton', 'String', 'Button 4', 'Parent', box2 );
uicontrol( 'Style', 'PushButton', 'String', 'Button 5', 'Parent', box2 );
% Set the dock/undock callback
set( panel{1}, 'DockFcn', {@nDock, 1} );
set( panel{2}, 'DockFcn', {@nDock, 2} );
set( panel{3}, 'DockFcn', {@nDock, 3} );
axes1 = axes( 'Parent', panel{1})
theta = 0:360;
plot(axes1,theta, sind(theta), theta, cosd(theta))
legend('sin','cos')
%-------------------------------------------------------------------------%
function nDock( eventSource, eventData, whichpanel ) %#ok<INUSL>
% Set the flag
panel{whichpanel}.Docked = ~panel{whichpanel}.Docked;
if panel{whichpanel}.Docked
% Put it back into the layout
newfig = get( panel{whichpanel}, 'Parent' );
set( panel{whichpanel}, 'Parent', box );
delete( newfig );
else
% Take it out of the layout
pos = getpixelposition( panel{whichpanel} );
newfig = figure( ...
'Name', get( panel{whichpanel}, 'Title' ), ...
'NumberTitle', 'off', ...
'MenuBar', 'none', ...
'Toolbar', 'none', ...
'CloseRequestFcn', {@nDock, whichpanel} );
figpos = get( newfig, 'Position' );
set( newfig, 'Position', [figpos(1,1:2), pos(1,3:4)] );
set( panel{whichpanel}, 'Parent', newfig, ...
'Units', 'Normalized', ...
'Position', [0 0 1 1] );
end
end % nDock
%-------------------------------------------------------------------------%
function nCloseAll( ~, ~ )
% User wished to close the application, so we need to tidy up
% Delete all windows, including undocked ones. We can do this by
% getting the window for each panel in turn and deleting it.
for ii=1:numel( panel )
if isvalid( panel{ii} ) && ~strcmpi( panel{ii}.BeingDeleted, 'on' )
figh = ancestor( panel{ii}, 'figure' );
delete( figh );
end
end
end % nCloseAll
end % Main function
2 Comments
Accepted Answer
Mohammad Askari
on 26 Jun 2018
Edited: Mohammad Askari
on 13 Apr 2022
Method 1.
As explained in the documentation, one way of doing it is to create a uicontainer parent for the axes to enable correct legend/colorbar behavior.
So simply change the axes creation line to the following:
axes1 = axes('Parent', uicontainer('Parent', panel{1}))
Method 2.
While this should work perfectly fine for most cases, you may not like the slight (not easily noticeable) shifting of the axes' position. I personally needed to come up with another solution for my own GUI due to my obsession with perfect positioning and alignment. This is not as neat as the above method, but it does the job and no longer needs to deal with the positioning of a uicontainer object which can get tricky in some cases.
You should first create a VBox or HBox container parent for your axes only. Then create the axes, add the legend, and set the Widths of the HBox or (Heights of the VBox) to [-1 0]. Finally, update your legend handle location value to your liking. I observed that resizing the figure (HBox/VBox axes container) resets the location of the legend object for some unknown reason. So I fixed this by adding a SizeChangedFcn callback to the container to fix this.
In short, you can achieve this by replacing your axes creation lines of your code with the following lines:
axesContainer = uix.HBox('Parent',panel{1},'SizeChangedFcn',{@GUIAxesLegendFix;'northeast'});
axes1 = axes('Parent', axesContainer);
theta = 0:360;
plot(axes1,theta, sind(theta), theta, cosd(theta))
LegendHandle = legend('sin','cos');
axesContainer.Widths = [-1 0];
LegendHandle.Location = 'northeast';
and add this callback function to the end of your code
function GUIAxesLegendFix(Handle,~,LegendLocation)
try Handle.Contents(2).Location = LegendLocation; catch, end
end
I just added a try, catch to the callback to prevent giving any error during resizing if you decide to add a legend to the container later manually. I also attached an updated version of your sample code with the method 2 solution. I suggest you try the more straightforward approach in the documentation and if you do not like the result, try the 2nd method.
0 Comments
More Answers (0)
See Also
Categories
Find more on Migrate GUIDE Apps in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!