Matlab 将数据提示堆栈放在轴标签的顶部,并在对轴位置进行更改后更新轴标签
此问题仅适用于unix matlabs,windows用户将无法复制它。 我在尝试创建位于y轴标签顶部的数据提示时遇到问题。下图说明了这一问题: 如您所见,在ylabel附近创建的数据提示将位于ylabel文本的底部,,而期望的效果正好相反:数据提示位于轴标签的顶部 我用下面的代码(不是很小的代码)生成了这个图。您可以删除带有Matlab 将数据提示堆栈放在轴标签的顶部,并在对轴位置进行更改后更新轴标签,matlab,plot,Matlab,Plot,此问题仅适用于unix matlabs,windows用户将无法复制它。 我在尝试创建位于y轴标签顶部的数据提示时遇到问题。下图说明了这一问题: 如您所见,在ylabel附近创建的数据提示将位于ylabel文本的底部,,而期望的效果正好相反:数据提示位于轴标签的顶部 我用下面的代码(不是很小的代码)生成了这个图。您可以删除带有%注释的行,也可以删除,甚至只需添加数据提示−78,而不是一个循环,以实现更快的测试脚本,但我离开这个代码,如果有人有一天希望它创建自定义数据(在这种情况下,也考虑看):
%注释的行,也可以删除,甚至只需添加数据提示−78,而不是一个循环,以实现更快的测试脚本,但我离开这个代码,如果有人有一天希望它创建自定义数据(在这种情况下,也考虑看):
我试过:
- 将所有数据提示添加到顶部
- ui将标签固定到底部(这两个标签都不起作用,因为ylabel句柄不在轴子句柄中)
更新:实施@horchler”解决方案后,出现了一个新问题:缩放和平移轴时,轴标签也会移动。我找到了一个小补丁,我改变了以下方面:
- 将datatip z值设置为1,使其始终高于Y轴z
- 在发生平移或缩放运动后重新创建标签。为此,我实现了
localAxisUpdate
函数,该函数获取旧的ylabel属性,将其替换为新属性,并重置除ylabel位置之外的所有可设置属性。为了这个,我用了这个
生成的代码如下所示:
function test
gradientStep = 1e-1;
x=-100:gradientStep:100; xSize=numel(x);
y=x.^3-x.^2;
figH=figure(42);
lineH=plot(x,y);
ylabel('YLabel (YUnits)','FontSize',16)
xlabel('XLabel (XUnits)','FontSize',16)
dcH=datacursormode(figH);
%nTips = 20;
%for pos = round(linspace(2,xSize,nTips))
pos = find(x>-78,1);
datatipH=dcH.createDatatip(lineH,...
struct('Position',[x(pos) y(pos) 1]));
orientation = 'top-left';
if pos>1
tipText{1} = 'The grandient here is: ';
tipText{2} = ['\Deltax:',sprintf('%d',x(pos)-x(pos-1)),' XUnits'];
tipText{3} = ['\Deltay:',sprintf('%d',y(pos)-y(pos-1)),' YUnits'];
else
tipText = 'Cannot calculate gradient here.';
end
bkgColor = [1 1 .5]; % Light Yellow
fontSize = 12;
set(datatipH,'StringFcn',(@(~,~) tipText),'Orientation',...
orientation,'backGroundColor',bkgColor,'FontSize',...
fontSize,'Draggable','on');
datatipTextBoxH=get(datatipH,'TextBoxHandle');
datatipTextBoxH=get(datatipH,'TextBoxHandle');
set(datatipTextBoxH,'HorizontalAlignment','left',...
'VerticalAlignment','top','Margin',0.02,'Interpreter',...
%end
% Set changes due to zoom and pan to also use adaptativeDateTicks:
set(zoom(figH),'ActionPostCallback',...
@(~,~) localAxisUpdate(gca));
set(pan(figH),'ActionPostCallback',...
@(~,~) localAxisUpdate(gca));
end
function localAxisUpdate(aH)
% Fix axis label on top of datatip:
ylh = get(aH,'YLabel');
% Get original YLabel properties
ylstruct = get(ylh);
% Get settable fields:
yfieldnames=fieldnames(rmfield(set(ylh),'Position'))';
% Remove old label:
delete(ylh)
% Create new one:
ylh = ylabel(aH,'Dummy');
% Send it bottom:
ylpos = get(ylh,'Position');
set(ylh, 'Position', [ylpos(1:2) 0]);
% Reset new ylabel to old values:
for field=yfieldnames
field = field{1};
set(ylh,field,ylstruct.(field));
end
end
这种方法会产生一种不需要的效果,即ylabel将在图形上移动,直到松开鼠标按钮如何消除这种不必要的影响?
我认为解决方案可能与中所做的差不多,但现在我需要ylabel postset属性的侦听器。有人知道怎么做吗?如果您是windows用户,您也可以尝试提供帮助,在对图形进行更改(平移、缩放或其他操作)后,我只需重置y标签的位置如何通过y标签的手柄显式设置其z位置?如果我把这个放在你的循环之后,它在R2012b中似乎是有效的:
ylh = get(gca,'Ylabel')
ylpos = get(ylh,'Position');
set(ylh,'Position',[ylpos(1:2) 0]);
如果我调整z位置,我可以让y标签弹出,甚至在数据提示之间交错。我不完全确定这是一个bug还是一个特性,但有时在渲染问题上会有一些变通方法,包括稍微调整元素的位置,让Matlab重新计算并重新绘制图形。这是一种同时使用这两种方法的变通方法,在缩放/平移多个绘图时非常有用,而且绘图的可视性也很好
创建一个轴(hax_1),其中包含要打印的函数,不包含数据提示
创建一个轴(hax_2),其中包含要打印的函数和数据提示,但不包含轴标签
将hax_2可见性设置为“关闭”(这将在第一个轴标签上方绘制数据提示)
用链接轴([hax_1 hax_2],'xy')链接2个轴;(其中一个轴上的缩放和平移将动态修改第二个轴)
这将为您的第一个代码(不是编辑的代码)提供:
我使用的是OSX 10.8.4,R2012b,与您的问题相同。这里,建议的解决方案在轴标签上方绘制数据提示,并允许缩放/平移,而无需使用matlab的未记录功能。太棒了!谢谢,这正是我需要的。想不到答案会这么简单!我现在不结束这个问题,以防有人想为未来的“几代人”改进答案。很高兴它对你有用。我担心您可能正在使用一个版本的Matlab,其中有一些bug会阻止它工作。有很多错误,只需要稍微调整元素的位置,就能让Matlab重新渲染所有内容。让它一直打开直到赏金结束或者你想什么时候打开都可以。让我惊讶的是,他的原始代码在2012b已经可以正常工作了。@Werner:这与原始问题相比是一个相当大的变化,原始问题没有任何关于缩放和平移的指示。这几乎是第二个问题——制作动态情节完全是另一回事,在我的经验中充满了问题,我不想费心。而你正试图让一个没有文档记录的功能发挥作用。我认为这一新问题源于手动设置标签位置,然后打破了所有依赖于创建位置/方式的Matlab脆弱的平移/缩放方法。基本上,标签恢复为与其他绘图元素一起移动的通用文本。此外,我认为其他人在创建自定义绘图时也遇到了移动标签和轴刻度标签的问题。这真是一场噩梦。它似乎用自己的版本覆盖了平移和缩放功能。不知道它有多好。仅供参考,您的原始代码在R2013a(WinXP)中无需修改即可工作:我也在使用Matlab R2013a,但在MacOs 10.8.4上。添加了一个请求来检查这是否真的是一个与平台相关的问题。做得很好。链接轴的实际“使用”
。那么,数据提示被放在一个不可见的轴上,该轴与与其对齐的主轴相连?我本以为一个无形轴心的孩子会继承无形。使用此技术可能会解决其他错误-尽管可能需要额外的处理/回调,这可能会有点昂贵-但是对于许多绘图来说,这通常不是太大的问题。轴和绘图都具有可见性属性。在顶层,只有轴不可见,绘图及其子项(包括数据提示)仍然可见。当需要密集的数据表示时,我会使用这个技巧
ylh = get(gca,'Ylabel')
ylpos = get(ylh,'Position');
set(ylh,'Position',[ylpos(1:2) 0]);
gradientStep = 1e-1;
x=-100:gradientStep:100; xSize=numel(x);
y=x.^3-x.^2;
figH=figure(42);
plot(x,y);
ylabel('YLabel (YUnits)','FontSize',16)
xlabel('XLabel (XUnits)','FontSize',16)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% modification starts
hax_1 = gca;
hax_2 = axes('Position', get(hax_1,'Position'));
lineH = plot(x,y);
linkaxes([hax_1 hax_2],'xy');
set(hax_2,'Visible', 'off');
% modification ends
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dcH=datacursormode(figH);
nTips = 20; % May change the loop for a datatip at x=-78.
for pos = round(linspace(2,xSize,nTips))
datatipH=dcH.createDatatip(lineH,struct('Position',[x(pos) y(pos)]));
orientation = 'top-left';
if pos>1
tipText{1} = 'The grandient here is: ';
tipText{2} = ['\Deltax:',sprintf('%d',x(pos)-x(pos-1)),' XUnits'];
tipText{3} = ['\Deltay:',sprintf('%d',y(pos)-y(pos-1)),' YUnits'];
else
tipText = 'Cannot calculate gradient here.';
end
bkgColor = [1 1 .5]; % May be removed.
fontSize = 12; % May be removed.
set(datatipH,'StringFcn',(@(~,~) tipText),'Orientation',orientation,'backGroundColor',bkgColor,'FontSize',fontSize,'Draggable','on'); % Only set text and orientation needed.
datatipTextBoxH=get(datatipH,'TextBoxHandle');
set(datatipTextBoxH,'HorizontalAlignment','left','VerticalAlignment','top','Margin',0.02,'Interpreter','tex','FontName','Courier','FontSize',fontSize); % May be removed.
end