3

サブプロットに単純なラベルを付けたいと思います。残念ながら、私は醜い振る舞いをしています。次の関数を検討してください。

function h = set_label1(label)
tlh = get(gca, 'Title');
if strcmp(get(tlh, 'String'), '')
    title(' ');
end
ylh = get(gca, 'YLabel');
if strcmp(get(ylh, 'String'), '')
    ylabel(' ');
end

ylp = get(ylh, 'Position');
x = ylp(1);

tlp = get(tlh, 'Position');
y = tlp(2);

h = text('String', label, ...
        'HorizontalAlignment', 'right',...
        'VerticalAlignment', 'Baseline', ...
        'FontUnits', 'pixels', ...
        'FontSize', 16, ...
        'FontWeight', 'bold', ...
        'FontName', 'Arial', ...
        'Position', [x y 0]);
end

簡単なテスト実行を次に示します。

figure;
h1 = axes('OuterPosition', [0,0,.5 1]);
set(h1,'LooseInset',get(h1,'TightInset'));
h2 = axes('OuterPosition', [.5,0,.5 1]);
set(h2,'LooseInset',get(h2,'TightInset'));

axes(h1);
plot([0 1], [4 5]);
set_label1('A');  

axes(h2);
plot([0 1], [4 5]);
set_label1('B');

私が得る写真は次のとおりです。

ここに画像の説明を入力

Figure のサイズを変更すると、ラベルが正しい位置になくなります。それは結構です、私はそれを期待していました(それらを元の場所に戻す方法を知っていて、それを教えてくれたらとてもうれしいです).

私が直面している問題は、「データ」単位でラベルの位置を指定したくないということです。代わりに、正規化された単位を使用したいと思います。そのため、関数の変更された形式を使用しました。これを使用してみましょう:

function h = set_label2(label)
tlh = get(gca, 'Title');
if strcmp(get(tlh, 'String'), '')
    title(' ');
end
ylh = get(gca, 'YLabel');
if strcmp(get(ylh, 'String'), '')
    ylabel(' ');
end

oldUnits = replace_prop(ylh, 'Units', 'normalized');
ylp = get(ylh, 'Position');
x = ylp(1);
set(ylh, 'Units', oldUnits);

oldUnits = replace_prop(tlh, 'Units', 'normalized');
tlp = get(tlh, 'Position');
y = tlp(2);
set(ylh, 'Units', oldUnits);

h = text('String', label, ...
        'HorizontalAlignment', 'right',...
        'VerticalAlignment', 'Baseline', ...
        'FontUnits', 'pixels', ...
        'FontSize', 16, ...
        'FontWeight', 'bold', ...
        'FontName', 'Arial', ...
        'Units', 'normalized',...
        'Position', [x y 0]);
end

function oldvalue = replace_prop(handle, propName, newvalue)
oldvalue = get(handle, propName);
set(handle, propName, newvalue);
end

同じテストを実行します:

figure;
h1 = axes('OuterPosition', [0,0,.5 1]);
set(h1,'LooseInset',get(h1,'TightInset'));
h2 = axes('OuterPosition', [.5,0,.5 1]);
set(h2,'LooseInset',get(h2,'TightInset'));

axes(h1);
plot([0 1], [4 5]);
set_label2('A');  

axes(h2);
plot([0 1], [4 5]);
set_label2('B');

以前とまったく同じ画像が得られます。唯一の問題は、サイズを変更すると何か問題が発生することです。

ここに画像の説明を入力

ラベルは実際には正しい位置にあります。しかし、私が使用した'LooseInset'and'TightInset'プロパティは、ラベルがないかのように軸を動作させているようです。これに対する修正はありますか?本当に私がしているのは、データ単位ではなく、正規化された単位でタイトルと ylabel の位置を取得することだけであり、これは混乱しているようです。

正規化された単位で取得する必要がある理由は、3D プロットを取得するときに、タイトルと zlabel に対してラベルを配置できるようにするためです。

4

2 に答える 2

2

後世のために、ここに私が使用することにしたバージョンがあります。期待どおりの動作をしますが、解決方法がわからない問題があります。OK、最初に朗報です。ここに という関数がありますaxes_label

function c = axes_label(varargin)

if isa(varargin{1}, 'char')
    axesHandle = gca;
else
    axesHandle = get(varargin{1}{1}, 'Parent');
end

if strcmp(get(get(axesHandle, 'Title'), 'String'), '')
    title(axesHandle, ' ');
end
if strcmp(get(get(axesHandle, 'YLabel'), 'String'), '')
    ylabel(axesHandle, ' ');
end
if strcmp(get(get(axesHandle, 'ZLabel'), 'String'), '')
    zlabel(axesHandle, ' ');
end

if isa(varargin{1}, 'char')    
    label = varargin{1};
    if nargin >=2
        dx = varargin{2};
        if nargin >= 3
            dy = varargin{3};
        else
            dy = 0;
        end
    else
        dx = 3;
        dy = 3;
    end
    h = text('String', label, ...
        'HorizontalAlignment', 'left',...
        'VerticalAlignment', 'top', ...
        'FontUnits', 'pixels', ...
        'FontSize', 16, ...
        'FontWeight', 'bold', ...
        'FontName', 'Arial', ...
        'Units', 'normalized');
    el = addlistener(axesHandle, 'Position', 'PostSet', @(o, e) posChanged(o, e, h, dx, dy));
    c = {h, el};
else
    h = varargin{1}{1};
    delete(varargin{1}{2});
    if nargin >= 2    
        if isa(varargin{2}, 'char')
            set(h, 'String', varargin{2});
            if nargin >=3
                dx = varargin{3};
                dy = varargin{4};
            else
                dx = 3;
                dy = 3;
            end
        else
            dx = varargin{2};
            dy = varargin{3};
        end
    else
       error('Needs more arguments. Type help axes_label'); 
    end
    el = addlistener(axesHandle, 'Position', 'PostSet', @(o, e) posChanged(o, e, h, dx, dy));
    c = {h, el};
end
posChanged(0, 0, h, dx, dy);
end

function posChanged(~, ~, h, dx, dy)
    axh = get(h, 'Parent');
    p = get(axh, 'Position');
    o = get(axh, 'OuterPosition');
    xp = (o(1)-p(1))/p(3);
    yp = (o(2)-p(2)+o(4))/p(4);
    set(h, 'Units', get(axh, 'Units'),'Position', [xp yp]);
    set(h, 'Units', 'pixels');
    p = get(h, 'Position');
    set(h, 'Position', [p(1)+dx, p(2)+5-dy]);
    set(h, 'Units', 'normalized');
end

わかりました、では、このくだらない関数をどのように使用しますか? 私はこれらの用途を持つことができるようにそれを作りました:

%   c = axes_label('label')
%      Places the text object with the string 'label' on the upper-left 
%      corner of the current axes and returns a cell containing the handle
%      of the text and an event listener.
%
%   c = axes_label('label', dx, dy)
%      Places the text object dx pixels from the left side of the axes
%      and dy pixels from the top. These values are set to 3 by default.
%
%   c = axes_label(c, ...)
%      Peforms the operations mentioned above on cell c containing the
%      handle of the text and the event listener.
%
%   c = axes_label(c, dx, dy)
%      Adjusts the current label to the specifed distance from the
%      upper-left corner of the current axes.

前と同じテストを実行すると、次のようになります。

figure;
h1 = axes('OuterPosition', [0,0,.5 1]);
set(h1,'LooseInset',get(h1,'TightInset'));
h2 = axes('OuterPosition', [.5,0,.5 1]);
set(h2,'LooseInset',get(h2,'TightInset'));

axes(h1);
plot([0 1], [4 5]);
axes_label('A');  

axes(h2);
plot([0 1], [4 5]);
axes_label('B', 250, 250);

今、私は望んでいたものを手に入れました。ラベル「A」は、軸の外箱の左上隅に設定されています。また、ラベル BI は、左上隅から 250 ピクセルになるように明示的に設定しています。ここにプロットがあります:

ここに画像の説明を入力

この関数で私が気に入っているのは、関数から返されたセルを保存してから戻すと、位置を変更できることです。たとえばlabel = axes_label('A');、コマンド プロンプトで実行するlabel = axes_label(label, 10, 20);と、ラベルが移動するのがわかります。

私が今直面している問題は、機能に関連していますexport_fig

これを使用しようとすると:

export_fig('testing.png', '-nocrop', '-painters');

すると、これが私が得た図です。

ここに画像の説明を入力

これが、私がラベル B を誇張した理由です。イベント リスナーを追加する前は、export_fig は、ラベルを配置した場所にラベルを印刷する際に問題なく機能していました。しかし、どういうわけか今 export_fig はそれが主張していることをしません。主に画像をエクスポートする

画面に表示されているとおりに再現された図形/軸

代わりにオプションを削除すると、次の-paintersようになります。

ここに画像の説明を入力

私はリスナーの経験がないため、コードにバグがある可能性があります。誰かがこの動作を修正したり、このコードを改善したりできる場合は、お気軽に回答して共有してください。

于 2012-06-23T01:56:37.313 に答える
1

まず第一に、タイトル/y-ラベルを使用してテキストを左上隅に配置するというあなたのアイデアが気に入っています:)

ここで、正規化された単位を使用する代わりに、データ ユニットを使用し続け、タイトルまたは Y ラベルの位置が変わるたびにイベント リスナーを作成し、それらの新しい値を使用して作成されたテキストを再調整します。

したがって、set_label1関数の最後に次を追加します。

addlistener(ylh, 'Position', 'PostSet', @(o,e) posChanged(o,e,h,1))
addlistener(tlh, 'Position', 'PostSet', @(o,e) posChanged(o,e,h,2))

両方の場合に使用されるコールバック関数を次に示します (最後の引数を使用して、idxx または y 座標を設定するかどうかを制御します)。

function posChanged(src,evt,hTxt,idx)
    posLabel = evt.NewValue;          %# new position of either title/y-label
    posText = get(hTxt, 'Position');  %# current text position
    posText(idx) = posLabel(idx);     %# update x or y position (based on idx)
    set(hTxt, 'Position',posText)     %# adjust the text position
end
于 2012-06-22T21:56:58.433 に答える