Code for a multicolumn legend in Matlab

旧时模样 提交于 2019-12-25 01:49:38

问题


I have designed an application called CLegend, which allows to build a multicolumn legend, whose code is

function CLegend(hax,numcol,Ley)
%# Inputs
% hax : handle of the axes object to which belongs the legend
% numcol: number of columns for the legend
% Ley: text strings (labels) for the legend

set(hax,'Units','normalized','Position',[0.1 0.1 0.8 0.8]);
set(hax,'Units','characters');
posAx = get(hax,'Position');
insAx = get(hax,'TightInset');

[legend_h,object_h] = legend(hax,Ley,'Units','characters','Location',...
    'South','Orientation','vertical');
posl = get(legend_h,'Position');
numlines = length(Ley);
if (numlines<numcol)
    numcol = numlines;
end

numpercolumn = ceil(numlines/numcol);

if (mod(numlines,numpercolumn) == 0)
    numcol = numlines/numpercolumn;
end

l = zeros(1,numlines);
a = zeros(1,numlines);
h = zeros(1,4);
for j=1:numlines
    h = get(object_h(j),'Extent');
    l(j) = h(3);
    a(j) = h(4);
    set(object_h(j),'Units','characters');
end

lmax = posl(3)*max(l);
hmax = posl(4)*max(a);
hLine = object_h(numlines+1);
xdata = get(hLine, 'xdata');
dx = xdata(2)-xdata(1);
di = 2;

sheight = hmax;     
height = hmax*numpercolumn-sheight/2;            
line_width = dx*posl(3);                
spacer = xdata(1)*posl(3);              
delta1 = spacer + line_width + spacer + lmax;
delta2 = line_width + spacer + lmax + spacer;
delta3 = lmax + spacer + line_width + spacer;
factx = 1/(posl(3)*numcol);
facty = 1/(hmax*numpercolumn);
width_l = numcol*delta1;

set(legend_h, 'Position', [posAx(1) + 0.5*(posAx(3)-width_l) posl(2) ...
   width_l  numpercolumn*hmax]);

col_ind = -1;
row_ind = -1;
j = 0;
for i=1:numlines,

    if strcmpi(orient,'horizontal'),
        if mod(i,numcol)==1,
            row_ind = row_ind+1;
        end
        col_ind = mod(i,numcol)-1;
        if col_ind == -1,
             col_ind = numcol-1;
        end

    else
        if numpercolumn==1 || mod(i,numpercolumn)==1,
            col_ind = col_ind+1;
        end

        row_ind = mod(i,numpercolumn)-1;
        if row_ind == -1,
             row_ind = numpercolumn-1;
        end   
    end

    if (i==1)
        linenum = i+numlines;
    else
        linenum = linenum+di;
    end
    labelnum = i;

    set(object_h(linenum), 'ydata',facty*[height-row_ind*sheight ...
        height-row_ind*sheight]);
    set(object_h(linenum), 'xdata', factx*[spacer + j*delta2 ...
                spacer + j*delta2 + line_width]);
    set(object_h(linenum+1), 'ydata',facty*(height-row_ind*sheight));
    set(object_h(linenum+1), 'xdata', factx*(spacer+line_width/2));
    set(object_h(labelnum), 'Position', [j*delta3+spacer*2+line_width ...
        height-row_ind*sheight]);
    if (mod(i,numpercolumn)== 0)
        j = j + 1;   
    end
end
opl = get(legend_h,'OuterPosition');
set(hax, 'Position',[posAx(1) posAx(2)+opl(4) posAx(3) posAx(4)-opl(4)]);

set(legend_h, 'OuterPosition',[opl(1) (posAx(2)-insAx(2))/2 opl(3) opl(4)]);
set([hax,legend_h],'Units','normalized');
end

I have problems with it. I have tried it with a more complicated code but similar to this one that appears below.

function qq
fh = figure('Units','characters');
GrapWin = uipanel ('Parent',fh,'Units','characters','title','Graphic',...
    'Position',[135 5 120 40]);
haxes = axes('Parent',GrapWin,'Units','normalized','Position',[0.1 0.1 0.8 0.8]);
PanVD = uipanel('Parent',fh,'Units','characters','Position',[55 5 30 10],...
    'title','Dependent Variable');
VDlh = uicontrol('Parent',PanVD,'Style','listbox','Units',...
    'normalized','Position',[0 0 1 1],'String',{'X','Y','Z'},'Value',1,...
    'Callback',@VDLhCallback);
T = 0:pi/100:2*pi;
X = sin(T);
xlabel(haxes,'Time');
title(haxes,'Sine Function');
plot(haxes,T,X);
CLegend(haxes,3,{'Var X'});

function VDLhCallback (src,evt)
    value = get(VDlh,'Value');
    switch value
        case 1
        title(haxes,'Sine Function');
        plot(haxes,T,X);
        CLegend(haxes,3,{'Var X'});   
        case 2
        title(haxes,'Cosine Function');
        Y = cos(T);
        plot(haxes,T,Y);
        CLegend(haxes,3,{'Var Y'});   
        case 3
        Z = tan(T);
        title(haxes,'Tangent Function');
        plot(haxes,T,Z);
        CLegend(haxes,3,{'Var Z'});     

    end

end

end

It happens something that I do not understand because the first time that CLegend is called the legend appears not centered (respect to axes) but the following callings through the listbox options it does is centered. Other problem that occurs is that if I delete the command line set(haxes,'Units','normalized') then, although the legend is centered, the axes appear with a reduced size. I also have found that the first time Clegend is calles, the position of the axes (variable posAx) is different from the following callings (in which posAx is always the same). I have thought that when the units were changed, the position of the object was not changed but this problem arises doubts inside my mind.


回答1:


In the Figure Properties documentation, it is said of Unit

This property affects the CurrentPoint and Position properties. If you change the value of Units, it is good practice to return it to its default value after completing your computation so as not to affect other functions that assume Units is the default value.

Can it explain your problems?




回答2:


After a lot of proofs, I have found that my problem was the resizing of the figure. The first time CLegend was called the figure window had its original size. The following calls of CLegend happened with the figure windows maximized.



来源:https://stackoverflow.com/questions/8380427/code-for-a-multicolumn-legend-in-matlab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!