Search code examples
matlabplotfont-sizelegend-properties

FontSize for the image's legend in Matlab


I have the following code:

X = 0:pi/100:0.25*pi;
Y1 = sin(X);
Y2 = cos(X);
Y3 = tan(X);
fh = figure('toolbar','none','menubar','none','Units','characters');
Pan1 = uipanel(fh,'Units','normalized','Position',[0 0 0.5 1],'title',...
  'Panel1');
Pan2 = uipanel(fh,'Units','normalized','Position',[0.5 0 0.5 1],'title',...
  'Panel2');
haxes = axes('Parent',Pan2,'Units', 'normalized','Position',...
[0.125 0.1 0.75 0.75]);
hplot = plot(haxes,X,Y1,X,Y2,X,Y3);
xlabel(haxes,'Time (second)');
ylabel(haxes,'Amplitude (meter)');
title(haxes,'Trigonometric functions');
Ley = {'Sine function','Cosine function','Tangent function'}; %# legend's strings values
legend(haxes,Ley,'Location','SouthOutside');
[FileName,PathName,FilterIndex] = uiputfile('*.bmp;*.png;*.jpg;*.tif','Save as');
ftmp = figure('Menu','none','Toolbar','none','Units','normalized',...
  'Position',[-1000 -1000 1 1]);
set(gcf,'PaperPositionMode','auto');
set(gcf,'InvertHardcopy','off');
new_axes = copyobj(haxes, ftmp);
legend(new_axes,Ley,'Location','SouthOutside','FontSize',8);
set(new_axes,'Units','normalized','Position',[0.1 0.1 0.8 0.8]);
fmtgraf = {'-dbmp','-dpng','-djpeg','-dtiff'};
fmt = fmtgraf{FilterIndex};
print(ftmp,fmt,FileName,'-r0');
delete(ftmp);
delete(fh);

As seen in the code, the command line

legend(new_axes,Ley,'Location','SouthOutside','FontSize',8);

is run before the command line

 set(new_axes,'Units','normalized','Position',[0.1 0.1 0.8 0.8]);

Because of it, the image appears cutted by its low part as seen below (independently of the existence or no existence of the property/value 'FontSize')

If the command line

 legend(new_axes,Ley,'Location','SouthOutside','FontSize',8);

is run after the command line

 set(new_axes,'Units','normalized','Position',[0.1 0.1 0.8 0.8]);

now the image is cutted by its low part but in this case it is not seen neither the xlabel text nor the legend box (as seen below)

If 'FontSize',8 is suppressed, all is Ok. How can I fix this if I want that the legend to have a lesser size?


Solution

  • It works fine for me too... You have to understand that LEGEND basically creates another axis instance inside the figure.

    Now you are placing it using 'SouthOutside' location, so it will try to resize the existing axis to place itself underneath it, but if you don't leave it enough space it might not fit, especially as you are using 'normalized' units which let the axes auto-resize given the parent container size.

    Try to vertically shrink the main plot axis a bit in advance, to give the legend more room...

    Also the order of commands does matter. Compare this:

    new_axes = copyobj(haxes, ftmp);
    legend(new_axes, Ley, 'Location','SouthOutside', 'FontSize',8);
    set(new_axes, 'Units','normalized', 'Position',[0.1 0.1 0.8 0.8]);
    

    against:

    new_axes = copyobj(haxes, ftmp);
    set(new_axes, 'Units','normalized', 'Position',[0.1 0.1 0.8 0.8]);
    legend(new_axes, Ley, 'Location','SouthOutside', 'FontSize',8);
    

    EDIT:

    As I mentioned, LEGEND creates just another axis. Therefore for ultimate control, you could manually position all the axes in the figure yourself (specify actual positions instead of relying on "outside" values for the 'Location' property exposed by the legend function).. Here is an example to illustrate:

    %# create a normal plot
    clf
    hAx = axes();
    plot(hAx, rand(10,3))
    xlabel(hAx, 'xlabel'), title(hAx,'title')
    
    %# add a legend on the inside and record the axis outerposition (in pixels)
    hLgnd = legend(hAx, {'1' '2' '3'}, 'Location','South', 'FontSize',8);
    set(hLgnd, 'Units','pixels')
    op = get(hLgnd,'OuterPosition');
    set(hLgnd, 'Units','normalized')
    
    %# resize the plot axis vertically to make room for the legend
    set(hAx, 'Units','pixels')
    pos = get(hAx,'Position');
    ins = get(hAx,'TightInset');
    set(hAx, 'Position',[pos(1) pos(2)+op(4) pos(3) pos(4)-op(4)])
    set(hAx, 'Units','normalized')
    
    %# move the legend to the bottom in the free space
    set(hLgnd, 'Units','pixels')
    set(hLgnd, 'OuterPosition',[op(1) (pos(2)-ins(2))/2 op(3) op(4)])
    set(hLgnd, 'Units','normalized')
    

    screenshot

    Try it out for different figure sizes and rerun the code.. Note that if you want the axes to correctly adjust their sizes automatically when you resize the figure, you have to do a similar thing as the above code inside the 'ResizeFcn' event handler of the figure, ie:

    set(gcf,'ResizeFcn',@myEventHandler)