我想给我做一个简单标签的子图。不幸的是,我的行为很丑陋。考虑以下功能:
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');
我获得的图片是:
如果您调整图形大小,标签将不再处于正确的位置。这很好,我期待它(如果你知道如何把它们放回原处,你告诉我们这会让我很开心)。
我面临的问题是我不想在'数据'单位中指定标签的位置。 相反,我想使用标准化单位。所以我使用了修改后的函数形式。现在让我们使用它:
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'
和'TightInset'
属性使轴的行为就像没有标签一样。
有没有解决这个问题?实际上,我所做的只是将标题和ylabel的位置放在标准化单位而不是数据单元中,这似乎搞得一团糟。
我需要在标准化单位中获取它的原因是,当我们得到3D图时,我可以相对于标题和zlabel定位标签。
答案 0 :(得分:2)
为了后人的缘故,这里是我决定使用的版本。它做了我期望它做的事情,但现在我遇到了一个我不知道如何解决的问题。好的,首先是好消息,这里是名为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'设置在轴的Outerbox的左上角。标签B我明确地将其设置为距其左上角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
,那么我们得到这个:
代码中可能存在一个错误,因为我没有听众的经验,因此如果有人可以修复此行为和/或可以改进此代码,请随意这样做并分享它作为答案。
答案 1 :(得分: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))
这里是用于两种情况的回调函数(我们使用最后一个参数idx
来控制是否设置x或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