Get from Ico-github-logo

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

» Watch video

Highlights from
legendflex.m: a more flexible, customizable legend

  • legendflex.m
  • getpos.m
  • setgetposexamples.m
  • setpos.m
  • README.m
    |legendflex.m|: a more flexible, customizable legend
  • View all files
4.9 | 40 ratings Rate this file 125 Downloads (last 30 days) File Size: 562 KB File ID: #31092 Version: 1.9
image thumbnail

legendflex.m: a more flexible, customizable legend


Kelly Kearney (view profile)


18 Apr 2011 (Updated )

Create a legend with more flexible positioning and labeling capabilities

Editor's Notes:

This file was selected as MATLAB Central Pick of the Week

| Watch this File

File Information

This function offers a more flexible version of the legend command. It uses a different method of positioning the legend (placing it relative to any axis, object, or figure), as well as options to:
- organize legend text and symbols in a grid with a specified number of rows and/or columns
- rescale the horizontal space used by each legend symbol
- create multiple legends for the same axis
- add a title to the legend within the legend box


Setpos 1.2 Getpos 1.2 inspired this file.

MATLAB release MATLAB 7.10 (R2010a)
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (87)
06 Feb 2017 Prashanth hanmaiahgari


06 Jan 2017 DomJung

02 Sep 2016 Neil Dalchau

Can't believe I hadn't rated this function yet. It's fantastic. And Kelly is great at fixing bugs and pushing new versions. You can rely on this one...

02 Sep 2016 Neil Dalchau

19 Jul 2016 Heiko

Heiko (view profile)

Hi Kelly, I found a hiding issue by uiPanels when applying the function within uiPanels for recent Matlab Releases. As a solution I added a 'parent' input Parameter, i.e. hnew.leg = axes(..., 'parent', Opt.parent), whereras Opt.parent = figh in case no 'parent' is provided.

06 Jun 2016 Benjamin Green

Thanks for the quick reply, I have made some personal modifications to get the function to work, however they are just a crude band-aid and not a real solution to the problem.
I look forward to seeing the update.

Comment only
03 Jun 2016 Kelly Kearney

Kelly Kearney (view profile)


Thank you for pointing out this issue. I've traced the issue to a change in the way legend.m parses input and output arguments in the R2016a release. I've added this to the known issues for legendflex.m (, and will work on updating the function as soon as possible.

Comment only
01 Jun 2016 Benjamin Green

Great Tool, I've been using it for a while to overcome the inadequacies of the built in Legend function. However i have noticed that in r2016a, that the font input is no longer being respected. None of the text properties are being implemented. eg Font, Font Size Interpreter,Not sure if I'm doing something wrong because the same code works correctly in r2014b.

11 May 2016 OlivierMegel

19 Apr 2016 Maryam GH

14 Apr 2016 Roman

Roman (view profile)

Applying this very useful function in 2016a - contrary to earlier ML-versions - results in:
Warning: NARGCHK will be removed in a future release. Use NARGINCHK or NARGOUTCHK instead. Warning: NARGCHK will be removed in a future release. Use NARGINCHK or NARGOUTCHK instead.

Plugging NARGINCHK in getpos.m function brings error messages too many output ...

23 Oct 2015 Kesh Ikuma

Kesh Ikuma (view profile)

Oops, never mind. I somehow downloaded an older version of the file...

23 Oct 2015 Kesh Ikuma

Kesh Ikuma (view profile)

Nice work. But there is a bug on the first line (l.210): ID'ing HG2 handles. The handle argument is checked with isnumeric call which is no longer appropriate. Suggest simply using


Comment only
21 Sep 2015 Kelly Kyriakou

Very usefull!!!
How I could make it visilbe off and then on again?

26 Aug 2015 Søren Enemark

I have suggested a possible solution/work-around at
If VerticalAlignment is set to 'middle', it is relatively robust towards changes of FontSize...

Comment only
18 Aug 2015 Kelly Kearney

Kelly Kearney (view profile)



Latex/Tex is an ongoing problem with this function, but unfortunately one that doesn't have an easy, all-situations fix. Some workarounds are suggested in the above link.

Comment only
18 Aug 2015 Søren Enemark

Very nice function!
However, I would like to use latex (and not tex) as textinterpreter. E.g. by set(groot,'defaultTextInterpreter','latex'). This is possible with the function as it is, but it results in vertical misaligment between the plot line and the tag text, as I see it. Can you help me?

Comment only
25 Jun 2015 Jakob

Jakob (view profile)

Ok, I found why it was not working for me, it was my fault (but not a very obvious one): I used stem with the option 'filled' plus additional name-value-pairs (color etc.). This works at first and also when adding a legend if I dont request the objects as output. But the documentation on 'stem' shows that you should not use 'filled' plus more options. Doing it seems to mess up subtle things internally...

23 Jun 2015 Jakob

Jakob (view profile)

Great function. I am currently experiencing an error though, but I think it might be a problem of the matlab legend function rather than of legendflex. Maybe you can still give me a hint on how to solve it:

The problem appears with a plot that has three data sequences plottet using stem. The legendflex codeline that calls the matlab legend function produces a

Warning: Error updating Legend. Following is the chain of causes of the error:
Property color not found in class, or is not present in all elements of the array of class

> In defaulterrorcallback at 12
In C:\Program Files\MATLAB\R2014b\toolbox\matlab\scribe\private\legendHGUsingMATLABClasses.p>find_legend_info at 382
In C:\Program Files\MATLAB\R2014b\toolbox\matlab\scribe\private\legendHGUsingMATLABClasses.p>legendHGUsingMATLABClasses at 251
In legend at 118
In legendflex at 307

..., the legend-entries are not displayed and the returned h.obj is an empty double array. This creates an error later, when your code tries to get the Extent of the objects in h.obj (textExtent).
If I just use legend (not legendflex), I get the same warning if I request the legend-objects as outputs. If I dont, there is no warning and the legend-entries get displayed normally.

Do you have an idea? Thanks!

Comment only
13 May 2015 Elizabeth Jones

Great function. I haven't used all the capabilities, but I got a quick legend in three rows without any errors.

22 Apr 2015 Kelly Kearney

Kelly Kearney (view profile)

The resize function bug has now been fixed. To clarify, the feval messiness is just a wrapper function to call all the callback functions in succession (though I messed up the order of inputs in my earlier implementation, hence the error).

Comment only
20 Apr 2015 Kelly Kearney

Kelly Kearney (view profile)


Thanks for the feedback. I'll look into the resize function bug as soon as possible. Trying to rewrite this function so it's compatible with both old and new handle graphics has been more difficult than I expected, and obviously I haven't worked out all the bugs yet.

I've also added your enhancement requests to my Issues list on the GitHub page, and will hopefully be able to add both options sometime soon.

Comment only
20 Apr 2015 Joerg Huschke

I really appreciate this function. However, I have several issues with it, tried with R2011b:

1) I don't see it correctly handles figures already having a resize function defined. For me the function produces error:
Error using horzcat
The following error occurred converting from cell to function_handle:
Error using function_handle
Too many output arguments.

Error in legendflexNew (line 640)
set(figh, 'ResizeFcn', cellfun(@(x)feval(x,h,e), [rsz @updatelegfigresize]));

Which is quite obvious, as rsz is forced to be a cell just a few lines above this code line. When I fix this to
set(figh, 'ResizeFcn', cellfun(@(x)feval(x,h,e), [rsz {@updatelegfigresize}]));

I get the next error for this line, because the 'e' in the feval is undefined. I have no idea what the intention of this feval is Why should the resizefcn be set to the result of the evaluation of @updatelegfigresize or of the function stored in rsz, rather than the function itself. Totally confused… This problem did not exist in version of 2011 I had been using so far.

2) The function should support the 'location' input like mathworks original legend does. Basically translate it to the Anchor/Buffer pair as provided in the function help text. I've already done this in my private extension of the function.

3 When using the 'outside' variants of the legend location then the reference axis to which the legend shall be associated is not reduced to make room for the outside-legend, unlike for the mathworks original legend. So currently the outside positions are not really usable unless I shrink the axis myself before.

I'm really looking forward to a legend function where I don't have to make compromises, like now I have to go either for the mathworks-provided one with its extremely limited functionality or with the older legendflex (as the current version does not work for me at all, see issue 1 above) but then cannot use outside locations. Would it be possible to fix this?

Comment only
03 Apr 2015 Eric

Eric (view profile)


Thanks, that was definitely the issue. Forgot to add that new folder to my path. Great submission BTW.

01 Apr 2015 Kelly Kearney

Kelly Kearney (view profile)


Looks like you're using an old version of getpos. Check that you're using the version distributed with this package, and not a version downloaded separately (the original one, FEX entry 13927, hasn't been updated for HG2 graphics; my version has).

Comment only
01 Apr 2015 Eric

Eric (view profile)

Crashes at legpospx = getpos(h.leg, 'px'); (line 415) with

ll = plot(0:1:3,magic(4));

in Matlab 2015b with error message:

Undefined operator '~' for input arguments of type 'matlab.ui.Figure'.
Error in getpos (line 160)
if ~href % HREF is the Root object (no 'Position' property)
Error in legendflex (line 415)
legpospx = getpos(h.leg, 'px');

Comment only
25 Mar 2015 Ken Campbell

Kelly, thanks for posting this excellent contribution. I had my own crude code for working with legends but this is much better. Your code is flexible, has lots of useful options, and is supported by good documentation.

19 Mar 2015 Kelly Kearney

Kelly Kearney (view profile)


It's difficult to diagnose what's going wrong there without knowing what type of objects you're trying to label. I recently updated the code to better work with the new handle graphics. If you still see this error, can you email a full example that reproduces it?

Comment only
11 Mar 2015 Jonathan

Hi, Fantastic script. I have had no issues running it on R2014a. However, I upgraded to R2015a, and have since encountered a problem when I run:

lbl = {previous, current, 'raw data (limited QC)',seasonal,'+/-1std','+2std'};
[hgGroup1,now,c,mm,hgGroup2,ext]= legendflex(lbl, 'ref', gcf,...
'anchor', {'nw','nw'}, ...
'buffer',[140 -76], ...
'nrow',3, ...
'ncol',3, ...

The returned error is:
Undefined function or variable "idx".

Error in legendflex (line 545)
ynorm = (xy{2}- (1-idx*rowHeightNm))./rowHeightNm;

Not clear to me what I'm doing wrong.


Comment only
03 Feb 2015 Kelly Kearney

Kelly Kearney (view profile)


You're right, I wrote the contour workaround pretty hastily and didn't test it for the no-handle input option. Corrected version on its way!

Comment only
30 Jan 2015 lgstarn

Hi, I love your script. pre-R2014b it worked great but of course old version broke with the update. So I downloaded the new version, but I see what appears to be a bug in your code. On the line:

iscont = strcmp(get(legin{1}, 'type'), 'contour');

I get the error:
Error using get
Conversion to double from cell is not possible.

Error in legendflex (line 293)
iscont = strcmp(get(legin{1}, 'type'), 'contour');

That's because I'm calling it as so:

strcell = {'U','V'};

buffer = [20 0];
legendflex(strcell,'FontSize',12,'anchor', [4 4], 'buffer',buffer);

so legin{1} is a string cell, and the get call does not work. The workaround I put in place was to surround the whole thing with a check if legin{1} is a string cell:

% Create a temporary legend to get all the objects
if (~all(cellfun(@ischar, legin{1})))
iscont = strcmp(get(legin{1}, 'type'), 'contour');
if any(iscont)
% Not sure why, but 2014b needs contour labels to be listed last in a
% legend, or everything goes haywire

[srt, isrt] = sort(iscont);
legin{1} = legin{1}(isrt);
legin{2} = legin{2}(isrt);

It's kind of messy to have legin{1} mean different things with the way you call it with the M or h syntax. I recommend refactoring legin{1} to have consistent meaning after you get done parsing the args.

24 Jan 2015 Kelly Kearney

Kelly Kearney (view profile)


The box around the legend content should expand as necessary to fit all content, including the title. If you have an example where this doesn't happen, could you email me?

Comment only
18 Jan 2015 arnold

arnold (view profile)

it would be great if the box around the legend would scale with a given title.

Secondly, it would also be handy to be able to easily append something to all entries, like a unit [m] or something.

Comment only
15 Dec 2014 Kelly Kearney

Kelly Kearney (view profile)


The disappearing legends you're seeing are due to the subplot command (which deletes any existing axes overlapping its intended space). See for a full explanation.

Comment only
12 Dec 2014 Leo Simon

It's a great program, and does exactly what I need it to do. There appears to be a small problem, which can easily be avoided but it would be great if you could fix it. When using subplots, if you use the "anchor" flag *and* have a legend label that is long enough to extend outside of the plot area, then when you open a new subplot, the old legend disappears. The following example illustrates the problem. As noted, it only arises when the anchor and the longLegend flags are turned on. Obviously, one can get around this problem by increasing the 'Position' dimensions of the subplot

close all;
legFontSize = 5;
legXScale = 0.5;
longLegend = 1;
anchorOn = 1;
for ii=1:15;
hold on;
h{ii}(1) = plot(1:10);
h{ii}(2) = plot(2:11);
if longLegend;
currentLegend = {'This is a very very very long legend','nothing'};
currentLegend = {'This','nothing'};
if anchorOn;
if ii==2; keyboard;end;

Comment only
12 Dec 2014 Leo Simon

11 Dec 2014 Warwick

Very useful and much appreciated.

10 Dec 2014 Kelly Kearney

Kelly Kearney (view profile)

The code to reproduce the sample image is now available in the example on the GitHub page (follow the kakearney/legendflex-pkg link, and scroll to the bottom of the page).

@Martin: The getpos.m function is included in the download; make sure you add the setgetpos folder to your path.

Comment only
09 Dec 2014 Martin

Martin (view profile)

I'm using Matlab R2013a. If I use the example code I get the following error:

b = bar(rand(10,5),'stacked'); colormap(summer); hold on
x = plot(1:10,5*rand(10,1),'marker','square','markersize',12,...
'markeredgecolor','y','markerfacecolor',[.6 0 .6],...
'linestyle','-','color','r','linewidth',2); hold off
lbl = {'Carrots','Peas','Peppers','Green Beans','Cucumbers','Eggplant'};
% Rather than covering up data or resizing the axis, let's squeeze the
% legend into the margin at the top of the figure;
legendflex([b,x], lbl, 'ref', gcf, ...
'anchor', {'n','n'}, ...
'buffer',[0 0], ...
'nrow',2, ...

I get this error:

Undefined function 'getpos' for input arguments of type 'double'.

Error in legendflex_pre2014b (line 351)
legpospx = getpos(h.leg, 'px');

Error in legendflex (line 209)
[tmp{:}] = legendflex_pre2014b(varargin{:});

Error in rfefe (line 11)
legendflex([b,x], lbl, 'ref', gcf, ...

What is the problem? Anybody knows?


Comment only
09 Dec 2014 Warwick

Could you include example code for your quiver plot at Figure C? Thanks.

Comment only
06 Dec 2014 Kelly Kearney

Kelly Kearney (view profile)


Yes, I think that was due to a residual R2014b bug. I've done a bit of cleanup over the last few weeks, and your example works fine using my most recent version, which I just uploaded. Email me if you still have problems with this latest version.

Comment only
05 Dec 2014 Chris Garner

This works in 2013b:

clear all

r = 18;

b = bar(x,'stacked');

lbl = {'1','2','3','4','5'};

legendflex(b, lbl, 'ref', gcf, ...
'anchor', {'n','n'}, ...
'buffer',[15 0], ...
'nrow',1, ...
'anchor', [6 6]);

but I get this error in 2014b:

Error using legendflex (line 228)
Legend labels must be a cell array of

Error in test (line 13)
legendflex(b, lbl, 'ref', gcf, ...

Is this due to change in ML graphics?

Comment only
20 Nov 2014 Michelle Tadmor

Can your code help me enlarge legend marker sizes? I have a scatter plot with tiny dots but I want the legend to show the dots larger so one can see the colors better.

Comment only
25 Aug 2014 Jose

Jose (view profile)

Just in case somebody else would like to use the latex interpreter and an horizontal legend. A quick fix is to either add $^{~}$ or $_{~}$ if one wants to adjust the top or bottom height of the word, respectively. This worked for me.

Comment only
25 Aug 2014 Jose

Jose (view profile)

@ Kelly

thanks for the quick reply. I guess I will have to find some quick fix for this :)

Comment only
25 Aug 2014 Kelly Kearney

Kelly Kearney (view profile)


Legendflex does not always play nicely with the Latex interpreter, because the Latex interpreter interacts unpredictably with the Extent property of text objects (which I rely on to reposition everything). I'm uploading a small text document to this function to explain this. The document offers a few workarounds if text is running into each other or overflowing the legend box, but I'm not sure I have a good suggestion for misaligned baselines, as in your case. My crystal ball suggests things will be a bit better in the 2014b release, but still not perfect.

Comment only
25 Aug 2014 Jose

Jose (view profile)

great work! I believe I found a bug with the current program.

When trying to use it with the latex interpreter and having an horizontal legend, apparently, all word items in the legend must have the same height, otherwise the legend becomes not properly aligned.

Here is an example code:

close all
p1 = plot(1,1,'b-','LineWidth',linewidthl)
hold on
p2 = plot(1,1,'r--','LineWidth',linewidthl)
hold on
p3 = plot(1,1,'g--','LineWidth',1.5)

legendflex([p1,p2,p3], {'P','Ap','R'}, 'ref', gcf,...
'anchor', {'n','n'},...
'buffer', [0 0],...

Since Ap does not have the same heigth as P and R, Ap becomes unaligned. However, if Ap is switched to Ac, then all is OK. Anybody has experienced this problem before?

Comment only
11 Aug 2014 arnold

arnold (view profile)

works great but it would still be good to be able to move it around like the normal legend since you never know which position might obscure your data. I'd really like that option

24 Jul 2014 Tobias Benjamin Gram

How can I add extra white space after the legend text? The bounding box is to close to the text on the right hand side of the box.

Comment only
04 May 2014 Adam Danz

Adam Danz (view profile)

Great! Definitely flexible. Thanks!

Comment only
05 Sep 2013 Kelly Kearney

Kelly Kearney (view profile)


You're right, this function relies on the current convention of graphics handles being numeric... I'll update it if and when HG2 is officially released (and perhaps by then legends will be flexible enough that this function won't be needed anymore).

Comment only
05 Sep 2013 Werner

Werner (view profile)

Unfortunately this doesn't work for HG2 x(. But great submission!

Comment only
13 Aug 2013 Brett

Brett (view profile)

This is what I was looking for, but I had to fix it to work well for axes embedded in complicated layouts involving uipanels, uitabs, etc. I use the excellent GUI Layout Toolbox from here on the file exchange to have lots of resizeable panels for example.

The problem is that this function assumes the legend should be placed relative to the figure. Unfortunately if a nested uipanel is used as a reference, the getpos() function does not correctly return the figure coordinates relative to the anchor. To get the global figure coordinates for a nested object, the GUI's hierarchy must be traversed, and the left and bottom coordinates summed for each parent up to the figure level. Each control's position is relative to it's parent, not to the figure.

Fortunately there's a simpler solution. I made the legend a child of the 'ref' object and fixed anywhere that temporary axes were made to the figure to be to the ref object instead. I also added a check that if this parent object is an axes, to get it's parent since the legend axes can't be a child of another axes. Finally, in the case of a plot in a densely nested GUI, the resize function should be on the parent component, not on the entire figure. This way when I drag the boundaries between uipanels to resize them, the legend and axes resize with them. I'm still experimenting with it, but this seems to solve my problems thus far.

I'll wait on permission to post my code since the author listed a copyright in the source.

08 May 2013 Tobias Benjamin Gram

Great addon to Matlab. Especially the shrinking function removing the unwanted space between legend marker and legend text. Thanks

17 Apr 2013 James Ackman

Indeed, this function allows for flexible positioning of legend data without auto-resizing of your plot axes.

And as a bonus it is a great way to make a static legend-- as workaround for the often discussed problems of slow graphics performance when updating dynamic plot data with the base legend() command.

Comment only
17 Apr 2013 James Ackman

09 Apr 2013 Kesh Ikuma

Kesh Ikuma (view profile)

Thanks for sharing a very useful function!

I have one issue though. I'm creating an EPS figure using the built-in PRINT function (in conjunction with my submitted EPS Toolbox), and the legendflex texts overlap while built-in legend gets the exact same texts properly resized. It appears to be that the print resolution is not reflected properly (96 desektop dpi to e.g., 300 print dpi) Any clue how to work around this? If you'd like to see what I described, please contact me via email. Thanks!

20 Mar 2013 Henrik

Henrik (view profile)

Thank you very much Kelly, this fixed the problem

18 Mar 2013 Kelly Kearney

Kelly Kearney (view profile)

@Henrik: Technically, legends are axes (both regular legends and those generated by legendflex). It looks like Convert4publication.m filters out legends based on their Tag property (on line 153). If you add the following line in the same location, it should also filter out legendflex axes:

h(arrayfun(@(a) isappdata(a, 'legflex'), h)) = [];

Comment only
18 Mar 2013 Henrik

Henrik (view profile)

This is exactly what I have been looking for to help make nice plots. However, I have a problem with this function in combination with convertplot4publication:
I'm hoping you could be able to help me with this?
For some reason it sees the legend as a subplot.. Here's an example of the problem:

y1 = randn(1000,1);

Comment only
14 Mar 2013 Kelly Kearney

Kelly Kearney (view profile)


The warning you are receiving is one issued by the print function whenever it prints a figure with a ResizeFcn, and legendflex does add a resize function to figures. Setting your figure's 'PaperPositionMode' to 'auto' will avoid it (and save you the step of manually setting the page size). Or you could use a function like export_fig (FEX #23629), which in my opinion produces much better output without the quirks of print.

Comment only
14 Mar 2013 Leo Simon

Thanks very much for this program, it's very helpful. I'm having one problem, which may or may not be specific to legendflex. I'm using it to print my legend to a separate figure. I want to resize my legend to be the same size as a regular figure. I can do this on screen with


To match on paper what I have on screen I would normally use


But when I set 'PaperPosition' to the desired size, to preseve the larger sized legend, and then print, I get this message:

Warning: Positioning Figure for ResizeFcn. Set PaperPositionMode to 'auto' (match figure screen size) to avoid resizing and this warning.

I've never had this problem before, so wondering if it's something special about legendflex.

Any advice would be most appreciated!


18 Jan 2013 Kelly Kearney

Kelly Kearney (view profile)

A workaround for the vertical positioning issues with subscripts/superscripts pointed out by William: render the legend with Interpreter set to 'none', then reset it to 'tex' afterwards. You may need to use a larger text size on the initial render as well, and reset to the correct size afterwards (e.g. if text hits box). It's not a perfect fix, and introduces extra horizontal space between columns, but I haven't found a better way to deal with the issues of produced by tex formatting in legends.

Comment only
18 Jan 2013 William

This is exactly what I was looking for, thank you! It worked perfectly for the first application (legends in subplots).

When I tried to use it the second time, I noticed a bug. When I used the legend with subscripts, e.g., 'e_pp', the marker positions are shifted downward. Is there anyway to correct this?

Thanks again, I appreciate your work!

04 Oct 2012 Eric

Eric (view profile)

I am running into issues when using the PRINT command as follows:


It creates the eps fine but the legend boxes are not in th eproper location. I can fix that be setting the figure PaperPositionMode to 'auto', but I like to have the flexibility of resizing before I print. Also, sometimes (like with a single row legends, the end of the text is clipped by the legend box.

04 Oct 2012 Eric

Eric (view profile)

I am running into issues when using the PRINT command as follows:


It creates the eps fine but the legend boxes are not in th eproper location. I can fix that be setting the figure PaperPositionMode to 'auto', but I like to have the flexibility of resizing before I print. Also, sometimes (like with a single row legends, the end of the text is clipped by the legend box.

Comment only
24 Aug 2012 alexancer

25 Jul 2012 Clint Noack

12 Jul 2012 Erik Johnson

If legendflex is called like:

[legend_h, object_h, plot_h, text_str] = legendflex(h, strs, 'ncol', ncols, ... );

then a workaround for the column offset is:

% fix legendflex's subsequent column locations
h = findobj(object_h, 'type', 'line');
y = get(h, {'YData'});
y = repmat(ans(1:ceil(length(y)/2/ncols)*2,:), ncols, 1);
y = ans(1:length(h),:);
set(h, {'YData'}, y);

Comment only
11 Jul 2012 Erik Johnson

A VERY useful function. However, I get slight offsets in the vertical locations of the lines/markers in different columns. Have you seen this?

For example, the code:

nrows = 1;
ncols = 3;
n = nrows * ncols;
x = repmat([0;1], 1, n);
y = [zeros(1,n); (1:n)/n];
h = plot(x, y);
strs = num2cell(char('`'+(1:n)), 1)';
[legax,legh] = legendflex(h, strs, 'ncol', ncols);

cat(1,ans{:}); yline=reshape(ans(:,1),[],3)
cat(1,ans{:}); ymarker=reshape(ans(:,1),[],3)
cat(1,ans{:}); ytext=reshape(ans(:,2),[],3)

gives the results:

yline = [9.5388 9.2710 9.0032]
ymarker = [9.5388 9.2710 9.0032]
ytext = [4.3091 4.3091 4.3091]

showing that the text items are set at consistent locations, but the lines and markers are slightly offset. (Change nrows to, say, 8 and the same vertical offset happens on all elements of subsequent columns.)

Any suggestions?

P.S. This is in MATLAB (R2012a) on a Mac.

27 Apr 2012 Chris

Chris (view profile)

Very nice - thanks!
I wonder if anyone knows how to go a step beyond. That is, my legends are often like tables which I currently hand make as figures within figures. The table-like legend has row and column headings with only the symbols/line types in the cells instead of a label for every symbol/line. This is because the symbol itself might change to represent one variable and whether it's filled or open might represent another so it's identity is a combination of the row and column headings in the table.

09 Apr 2012 Dominic

07 Mar 2012 Camille Couzi

thanks a lot for this very useful code!!!

24 Jan 2012 Mukhtar Ullah

Mukhtar Ullah (view profile)

Thanks Kelly for your explanation. I am not sure what will I loose if I keep those lines commented out. At the moment, I am avoiding any figure resize when both legendflex and panel are at play.

Comment only
19 Jan 2012 Kelly Kearney

Kelly Kearney (view profile)

@Mukhtar Ullah

Regarding making legendflex play nicely with panel, I admit I never considered the possibility that a figure's resize function might be linked to an object method. I don't do object-oriented coding myself, so I have very little knowledge of the internal workings, scope, etc. of objects. So no promises to fix this, though I will look into it if I find some spare time.

Comment only
18 Jan 2012 Mukhtar Ullah

Mukhtar Ullah (view profile)

I just realized that it is possible to find the legendflex axes by
ax = getappdata(hfig, 'legflexchildren')
I now have another problem. When I use legendflex together with panel
any attempt to resize the figure results in the following error
Error using panel.resizeCallback
Cannot access method 'resizeCallback' in class 'panel'.

Error in legendflex>resizefig (line 637)
feval(Lf.oldrsz, hfig, ed);

Error using drawnow
Error while evaluating figure ResizeFcn

It turned out that commenting line 637 solves my problem.
Any idea of fixing this in a future release?


Comment only
14 Jan 2012 Mukhtar Ullah

Mukhtar Ullah (view profile)

Thank you Kelly for clarifying that. It occurred to me because with legend, it is possible to set properties such as interpreter, string,..using set directly on the axes handle.
A minor addition to legendflex will make it easier to find its handle using findobj and findall function. For example, if you add a tag 'legendflex' to the axes, findobj(gcf, 'tag', 'legendflex') would locate the axes.


Comment only
10 Jan 2012 Kelly Kearney

Kelly Kearney (view profile)

@Mukhtar Ullah,

I don't actually manually set the interpreter in this function, so it relies on the default. You can actually change this after the fact using set, as long as you return the object_h handles (see last syntax option); the first n indices of this array will correspond to the n text objects in the legend. This slightly obscure way of returning handles was chosen to be consistent with the original legend command.

Comment only
10 Jan 2012 Mukhtar Ullah

Mukhtar Ullah (view profile)

This function is the first serious fix to the long lasting problems Matlab has with legends.
The text interpreter is set none by this function and you could only change it when calling the function, and not later using SET. Is there a good reason for that?

10 Aug 2011 Ben

Ben (view profile)

Could you provide the example of getting the result as the screenshoot shows? I think the simple examples in the .m file is not fully demonstrate the capability of your function. Wish you could add more examples.

10 Aug 2011 Philipp

08 Aug 2011 Mario Liverpool

Very useful indeed!

17 Jun 2011 Kelly Kearney

Kelly Kearney (view profile)

Vertical alignment bug has been corrected, and I added some checks to make sure the figure resize doesn't crash when you remove a legend. Thanks to Jason for discovering these bugs.

Comment only
10 Jun 2011 Jason Kaeding

I guess it didn't take my first bug submission...

The vertical positioning of the patches is incorrect in the following code:

legendflex(gca,cellstr(num2str(column(1:10))),'ncol',5,'anchor',[6 2],'buffer',[0 -10])

Comment only
10 Jun 2011 Jason Kaeding

Another bug: if I delete the legend then resize my figure, I get an error...

??? Error using ==> getappdata
Invalid object handle

Error in ==> legendflex>resizefig at 621
Lf = getappdata(ax(ia), 'legflex');

??? Error while evaluating figure ResizeFcn

16 May 2011 Claudio

Well done! Very useful!

29 Apr 2011 Dan

Dan (view profile)

20 Apr 2011 1.1

Figure resize now re-links legend and labeled objects with updated line/patch properties.

16 Jun 2011 1.2

bug fixes: fixed error in function resize if you delete the legend, fixed minor vertical alignment issue

24 Jun 2011 1.3

Fixed bug where very wide titles were not completely enclosed in legend box.

11 Apr 2013 1.4

Now respects manual changes made by user (including legend height, width, and units) when resizing.

10 Jul 2014 1.5

- updated for R2014b graphics

12 Aug 2014 1.6

Added parameter to modify padding between legend box and text/symbols

26 Aug 2014 1.7

Added note regarding legendflex with the Latex interpreter

18 Aug 2015 1.8

- Corrected some remaining R2014b bugs; all graphics handles should now be objects rather than numeric if running in R2014b or later.
- Switched source to github repository

16 Nov 2016 1.9

Updated description (which was erased when the github link was added)

Contact us