MATLAB Answers

Help with GUI Layout toolbox

20 views (last 30 days)
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

Walter Roberson
Walter Roberson on 4 Mar 2018
Try
legend(axes1, {'sin','cos'})
Sankar Mahadevan
Sankar Mahadevan on 4 Mar 2018
Hi Walter, that doesn't work. I tried doing that.

Sign in to comment.

Accepted Answer

Mohammad Askari
Mohammad Askari on 26 Jun 2018
Edited: Mohammad Askari on 25 Oct 2019
Method 1.
One way of doing it as explained in the documentation is to create a uicontainer parent for axes to enable correct legend/colorbar behavior.
So simply change the axes creation line to the following:
axes1 = axes('Parent', uicontainer('Parent', panel{1}))
Method2.
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 on perfect positioning and alignment. This is not as neat as the above method, but does the job and no longer needs to deal with positioning of a uicontainer object which can get tricky for 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) actually 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 try, catch to the callback to prevent giving any error during resizing in case you decide to add legend to the container later manually. I also attached an updated version of your sample code with method 2 solution. I suggest you to try the easier approach in the documentation and if you do not like the result, try the 2nd method.

  0 Comments

Sign in to comment.

More Answers (0)

Sign in to answer this question.


Translated by