Код для многоколоночной легенды в Matlab - PullRequest
0 голосов
/ 05 декабря 2011

Я разработал приложение под названием CLegend, которое позволяет создавать многоколоночную легенду, код которой

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

У меня проблемы с этим. Я пробовал это с более сложным кодом, но похож на тот, который показан ниже.

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

Это происходит из-за того, что я не понимаю, потому что в первый раз, когда CLegend называется легендой, она появляется не по центру (относительно осей), а следующие вызовы через параметры списка, которые она делает, центрируются. Другая проблема, которая возникает в том случае, если я удаляю командную строку набор (haxes, 'Единицы измерения', 'нормализуется') затем, хотя легенда центрирована, оси отображаются с уменьшенным размером. Я также обнаружил, что в первый раз, когда Clegend является calles, положение осей (переменная posAx) отличается от следующих вызовов (в которых posAx всегда одинаково). Я думал, что когда единицы были изменены, положение объекта не изменилось, но эта проблема вызывает сомнения в моем разуме.

Ответы [ 2 ]

1 голос
/ 05 декабря 2011

В документации Свойства рисунка говорится о Unit

Это свойство влияет на свойства CurrentPoint и Position. если ты изменить значение единиц, рекомендуется вернуть его в значение по умолчанию после завершения вычислений, чтобы не влиять другие функции, которые принимают Units, являются значением по умолчанию.

Это может объяснить твои проблемы?

0 голосов
/ 07 декабря 2011

После множества доказательств я обнаружил, что моей проблемой было изменение размера фигуры. Первый раз, когда CLegend назывался, окно рисунка имело свой первоначальный размер. Следующие вызовы CLegend произошли с развернутыми окнами рисунка.

...